1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#ifndef ANDROID_DVR_BUFFER_HUB_CLIENT_H_
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#define ANDROID_DVR_BUFFER_HUB_CLIENT_H_
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <hardware/gralloc.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/channel_handle.h>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/client.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/file_handle.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/status.h>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <vector>
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/ion_buffer.h>
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka#include "bufferhub_rpc.h"
1552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace dvr {
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass BufferHubBuffer : public pdx::Client {
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using LocalHandle = pdx::LocalHandle;
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using LocalChannelHandle = pdx::LocalChannelHandle;
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  template <typename T>
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using Status = pdx::Status<T>;
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a new consumer channel that is attached to the producer. Returns
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // a file descriptor for the new channel or a negative error code.
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  Status<LocalChannelHandle> CreateConsumer();
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
30e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Poll(int timeout_ms);
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Locks the area specified by (x, y, width, height) for a specific usage. If
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // the usage is software then |addr| will be updated to point to the address
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // of the buffer in virtual memory. The caller should only access/modify the
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // pixels in the specified area. anything else is undefined behavior.
374d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  int Lock(int usage, int x, int y, int width, int height, void** addr);
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Must be called after Lock() when the caller has finished changing the
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // buffer.
414d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  int Unlock();
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Gets a blob buffer that was created with BufferProducer::CreateBlob.
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Locking and Unlocking is handled internally. There's no need to Unlock
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // after calling this method.
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetBlobReadWritePointer(size_t size, void** addr);
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Gets a blob buffer that was created with BufferProducer::CreateBlob.
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Locking and Unlocking is handled internally. There's no need to Unlock
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // after calling this method.
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetBlobReadOnlyPointer(size_t size, void** addr);
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Returns a dup'd file descriptor for accessing the blob shared memory. The
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // caller takes ownership of the file descriptor and must close it or pass on
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // ownership. Some GPU API extensions can take file descriptors to bind shared
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // memory gralloc buffers to GPU buffer objects.
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  LocalHandle GetBlobFd() const {
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Current GPU vendor puts the buffer allocation in one FD. If we change GPU
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // vendors and this is the wrong fd, late-latching and EDS will very clearly
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // stop working and we will need to correct this. The alternative is to use
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // a GL context in the pose service to allocate this buffer or to use the
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // ION API directly instead of gralloc.
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return LocalHandle(dup(native_handle()->data[0]));
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
6610e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar  // Get up to |max_fds_count| file descriptors for accessing the blob shared
6710e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar  // memory. |fds_count| will contain the actual number of file descriptors.
6810e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar  void GetBlobFds(int* fds, size_t* fds_count, size_t max_fds_count) const;
6910e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using Client::event_fd;
713079cb7c32421099a73e1a774b228635eeb3f189Corey Tabaka
723079cb7c32421099a73e1a774b228635eeb3f189Corey Tabaka  Status<int> GetEventMask(int events) {
733079cb7c32421099a73e1a774b228635eeb3f189Corey Tabaka    if (auto* client_channel = GetChannel()) {
743079cb7c32421099a73e1a774b228635eeb3f189Corey Tabaka      return client_channel->GetEventMask(events);
753079cb7c32421099a73e1a774b228635eeb3f189Corey Tabaka    } else {
763079cb7c32421099a73e1a774b228635eeb3f189Corey Tabaka      return pdx::ErrorStatus(EINVAL);
773079cb7c32421099a73e1a774b228635eeb3f189Corey Tabaka    }
783079cb7c32421099a73e1a774b228635eeb3f189Corey Tabaka  }
793079cb7c32421099a73e1a774b228635eeb3f189Corey Tabaka
8052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
8152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    if (auto* client_channel = GetChannel()) {
8252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      return client_channel->GetEventSources();
8352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    } else {
8452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka      return {};
8552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    }
8652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  }
8752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  native_handle_t* native_handle() const {
894d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar    return const_cast<native_handle_t*>(buffer_.handle());
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
912655e1cd5498749381701aa1fa7f29c66364a7efCorey Tabaka
924d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  IonBuffer* buffer() { return &buffer_; }
934d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  const IonBuffer* buffer() const { return &buffer_; }
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int id() const { return id_; }
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
9752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // A state mask which is unique to a buffer hub client among all its siblings
9852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // sharing the same concrete graphic buffer.
9952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  uint64_t buffer_state_bit() const { return buffer_state_bit_; }
10052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // The following methods return settings of the first buffer. Currently,
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // it is only possible to create multi-buffer BufferHubBuffers with the same
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // settings.
1044d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  uint32_t width() const { return buffer_.width(); }
1054d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  uint32_t height() const { return buffer_.height(); }
1064d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  uint32_t stride() const { return buffer_.stride(); }
1074d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  uint32_t format() const { return buffer_.format(); }
1084d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  uint32_t usage() const { return buffer_.usage(); }
1094d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  uint32_t layer_count() const { return buffer_.layer_count(); }
110044963e1dd0479035b6e5f2c6bd618bde7143710Jiwen 'Steve' Cai
111ec971362bc651d8c98febb8399981877da859c14Corey Tabaka  // TODO(b/37881101) Clean up producer/consumer usage.
1124d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  uint64_t producer_usage() const { return buffer_.usage(); }
1134d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  uint64_t consumer_usage() const { return buffer_.usage(); }
114ec971362bc651d8c98febb8399981877da859c14Corey Tabaka
11552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  uint64_t GetQueueIndex() const { return metadata_header_->queue_index; }
11652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; }
11752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko protected:
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit BufferHubBuffer(LocalChannelHandle channel);
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit BufferHubBuffer(const std::string& endpoint_path);
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  virtual ~BufferHubBuffer();
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
123e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Initialization helper.
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int ImportBuffer();
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
12652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // Check invalid metadata operation. Returns 0 if requested metadata is valid.
12752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int CheckMetadata(size_t user_metadata_size) const;
12852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
12952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // Send out the new fence by updating the shared fence (shared_release_fence
13052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // for producer and shared_acquire_fence for consumer). Note that during this
13152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // should only be used in LocalPost() or LocalRelease, and the shared fence
13252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // shouldn't be poll'ed by the other end.
13352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int UpdateSharedFence(const LocalHandle& new_fence,
13452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                        const LocalHandle& shared_fence);
13552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
13652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // IonBuffer that is shared between bufferhubd, producer, and consumers.
13752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  size_t metadata_buf_size_{0};
13852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  size_t user_metadata_size_{0};
13952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  BufferHubDefs::MetadataHeader* metadata_header_{nullptr};
14052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  void* user_metadata_ptr_{nullptr};
14152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  std::atomic<uint64_t>* buffer_state_{nullptr};
14252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  std::atomic<uint64_t>* fence_state_{nullptr};
14352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
14452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  LocalHandle shared_acquire_fence_;
14552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  LocalHandle shared_release_fence_;
14652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
14752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // A local fence fd that holds the ownership of the fence fd on Post (for
14852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // producer) and Release (for consumer).
14952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  LocalHandle pending_fence_fd_;
15052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
152e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  BufferHubBuffer(const BufferHubBuffer&) = delete;
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void operator=(const BufferHubBuffer&) = delete;
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Global id for the buffer that is consistent across processes. It is meant
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // for logging and debugging purposes only and should not be used for lookup
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // or any other functional purpose as a security precaution.
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int id_;
15952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  uint64_t buffer_state_bit_{0ULL};
1604d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar  IonBuffer buffer_;
16152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  IonBuffer metadata_buffer_;
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
164e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// This represents a writable buffer. Calling Post notifies all clients and
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// makes the buffer read-only. Call Gain to acquire write access. A buffer
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// may have many consumers.
167e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko//
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// The user of BufferProducer is responsible with making sure that the Post() is
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// done with the correct metadata type and size. The user is also responsible
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// for making sure that remote ends (BufferConsumers) are also using the correct
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// metadata when acquiring the buffer. The API guarantees that a Post() with a
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// metadata of wrong size will fail. However, it currently does not do any
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// type checking.
174e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// The API also assumes that metadata is a serializable type (plain old data).
175e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Imports a bufferhub producer channel, assuming ownership of its handle.
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static std::unique_ptr<BufferProducer> Import(LocalChannelHandle channel);
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static std::unique_ptr<BufferProducer> Import(
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      Status<LocalChannelHandle> status);
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
18252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // Asynchronously posts a buffer. The fence and metadata are passed to
18352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // consumer via shared fd and shared memory.
18452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int PostAsync(const DvrNativeBufferMetadata* meta,
18552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                const LocalHandle& ready_fence);
18652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Post this buffer, passing |ready_fence| to the consumers. The bytes in
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // |meta| are passed unaltered to the consumers. The producer must not modify
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // the buffer until it is re-gained.
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // This returns zero or a negative unix error code.
191e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Post(const LocalHandle& ready_fence, const void* meta,
19252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka           size_t user_metadata_size);
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  template <typename Meta,
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            typename = typename std::enable_if<std::is_void<Meta>::value>::type>
196e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Post(const LocalHandle& ready_fence) {
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return Post(ready_fence, nullptr, 0);
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
1992655e1cd5498749381701aa1fa7f29c66364a7efCorey Tabaka  template <typename Meta, typename = typename std::enable_if<
2002655e1cd5498749381701aa1fa7f29c66364a7efCorey Tabaka                               !std::is_void<Meta>::value>::type>
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Post(const LocalHandle& ready_fence, const Meta& meta) {
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return Post(ready_fence, &meta, sizeof(meta));
203e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Attempt to re-gain the buffer for writing. If |release_fence| is valid, it
206e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // must be waited on before using the buffer. If it is not valid then the
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // buffer is free for immediate use. This call will only succeed if the buffer
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // is in the released state.
209e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // This returns zero or a negative unix error code.
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Gain(LocalHandle* release_fence);
21152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int GainAsync();
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
213e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Asynchronously marks a released buffer as gained. This method is similar to
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // the synchronous version above, except that it does not wait for BufferHub
21552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // to acknowledge success or failure. Because of the asynchronous nature of
21652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // the underlying message, no error is returned if this method is called when
21752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // the buffer is in an incorrect state. Returns zero if sending the message
21852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // succeeded, or a negative errno code if local error check fails.
21952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
220e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Attaches the producer to |name| so that it becomes a persistent buffer that
222e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // may be retrieved by name at a later time. This may be used in cases where a
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // shared memory buffer should persist across the life of the producer process
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // (i.e. the buffer may be held by clients across a service restart). The
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // buffer may be associated with a user and/or group id to restrict access to
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // the buffer. If user_id or group_id is -1 then checks for the respective id
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // are disabled. If user_id or group_id is 0 then the respective id of the
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // calling process is used instead.
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int MakePersistent(const std::string& name, int user_id, int group_id);
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Removes the persistence of the producer.
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int RemovePersistence();
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  friend BASE;
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Constructors are automatically exposed through BufferProducer::Create(...)
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // static template methods inherited from ClientBase, which take the same
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // arguments as the constructors.
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Constructs a buffer with the given geometry and parameters.
242cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka  BufferProducer(uint32_t width, uint32_t height, uint32_t format,
2434d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar                 uint32_t usage, size_t metadata_size = 0);
244ec971362bc651d8c98febb8399981877da859c14Corey Tabaka  BufferProducer(uint32_t width, uint32_t height, uint32_t format,
245ec971362bc651d8c98febb8399981877da859c14Corey Tabaka                 uint64_t producer_usage, uint64_t consumer_usage,
2464d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar                 size_t metadata_size);
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Constructs a persistent buffer with the given geometry and parameters and
249e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // binds it to |name| in one shot. If a persistent buffer with the same name
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // and settings already exists and matches the given geometry and parameters,
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // that buffer is connected to this client instead of creating a new buffer.
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // If the name matches but the geometry or settings do not match then
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // construction fails and BufferProducer::Create() returns nullptr.
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  //
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Access to the persistent buffer may be restricted by |user_id| and/or
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // |group_id|; these settings are established only when the buffer is first
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // created and cannot be changed. A user or group id of -1 disables checks for
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // that respective id. A user or group id of 0 is substituted with the
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // effective user or group id of the calling process.
260cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka  BufferProducer(const std::string& name, int user_id, int group_id,
261cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka                 uint32_t width, uint32_t height, uint32_t format,
2624d3590f3fd0fd65f4e8758d3228de9f55cf135d0Hendrik Wagenaar                 uint32_t usage, size_t metadata_size = 0);
263ec971362bc651d8c98febb8399981877da859c14Corey Tabaka  BufferProducer(const std::string& name, int user_id, int group_id,
264ec971362bc651d8c98febb8399981877da859c14Corey Tabaka                 uint32_t width, uint32_t height, uint32_t format,
265ec971362bc651d8c98febb8399981877da859c14Corey Tabaka                 uint64_t producer_usage, uint64_t consumer_usage,
26652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                 size_t user_metadata_size);
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Constructs a blob (flat) buffer with the given usage flags.
269ec971362bc651d8c98febb8399981877da859c14Corey Tabaka  BufferProducer(uint32_t usage, size_t size);
270ec971362bc651d8c98febb8399981877da859c14Corey Tabaka  BufferProducer(uint64_t producer_usage, uint64_t consumer_usage, size_t size);
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Constructs a persistent blob (flat) buffer and binds it to |name|.
273cd52dd9f1b301854b4e1734e3741d9cef8f784b1Corey Tabaka  BufferProducer(const std::string& name, int user_id, int group_id,
274ec971362bc651d8c98febb8399981877da859c14Corey Tabaka                 uint32_t usage, size_t size);
275ec971362bc651d8c98febb8399981877da859c14Corey Tabaka  BufferProducer(const std::string& name, int user_id, int group_id,
276ec971362bc651d8c98febb8399981877da859c14Corey Tabaka                 uint64_t producer_usage, uint64_t consumer_usage, size_t size);
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
278e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Constructs a channel to persistent buffer by name only. The buffer must
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // have been previously created or made persistent.
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit BufferProducer(const std::string& name);
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Imports the given file handle to a producer channel, taking ownership.
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit BufferProducer(LocalChannelHandle channel);
28452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
28552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // Local state transition helpers.
28652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
28752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int LocalPost(const DvrNativeBufferMetadata* meta,
28852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                const LocalHandle& ready_fence);
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// This is a connection to a producer buffer, which can be located in another
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// application. When that buffer is Post()ed, this fd will be signaled and
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Acquire allows read access. The user is responsible for making sure that
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Acquire is called with the correct metadata structure. The only guarantee the
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// API currently provides is that an Acquire() with metadata of the wrong size
296e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// will fail.
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass BufferConsumer : public pdx::ClientBase<BufferConsumer, BufferHubBuffer> {
298e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
299e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // This call assumes ownership of |fd|.
300e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static std::unique_ptr<BufferConsumer> Import(LocalChannelHandle channel);
301e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static std::unique_ptr<BufferConsumer> Import(
302e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      Status<LocalChannelHandle> status);
303e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
304e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Attempt to retrieve a post event from buffer hub. If successful,
305e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // |ready_fence| will be set to a fence to wait on until the buffer is ready.
306e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // This call will only succeed after the fd is signalled. This call may be
307e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // performed as an alternative to the Acquire() with metadata. In such cases
308e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // the metadata is not read.
309e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  //
310e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // This returns zero or negative unix error code.
311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Acquire(LocalHandle* ready_fence);
312e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
313e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Attempt to retrieve a post event from buffer hub. If successful,
314e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // |ready_fence| is set to a fence signaling that the contents of the buffer
315e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // are available. This call will only succeed if the buffer is in the posted
316e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // state.
317e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Returns zero on success, or a negative errno code otherwise.
31852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size);
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
320e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Attempt to retrieve a post event from buffer hub. If successful,
321e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // |ready_fence| is set to a fence to wait on until the buffer is ready. This
322e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // call will only succeed after the fd is signaled. This returns zero or a
323e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // negative unix error code.
324e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  template <typename Meta>
325e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Acquire(LocalHandle* ready_fence, Meta* meta) {
326e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return Acquire(ready_fence, meta, sizeof(*meta));
327e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
328e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
32952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // Asynchronously acquires a bufer.
33052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
33152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
332e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // This should be called after a successful Acquire call. If the fence is
333e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // valid the fence determines the buffer usage, otherwise the buffer is
334e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // released immediately.
335e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // This returns zero or a negative unix error code.
336e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Release(const LocalHandle& release_fence);
33752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int ReleaseAsync();
338e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
339e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Asynchronously releases a buffer. Similar to the synchronous version above,
34052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // except that it does not wait for BufferHub to reply with success or error.
34152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // The fence and metadata are passed to consumer via shared fd and shared
34252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // memory.
34352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int ReleaseAsync(const DvrNativeBufferMetadata* meta,
34452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                   const LocalHandle& release_fence);
345e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
346e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // May be called after or instead of Acquire to indicate that the consumer
347e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // does not need to access the buffer this cycle. This returns zero or a
348e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // negative unix error code.
349e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int Discard();
350e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
351e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // When set, this consumer is no longer notified when this buffer is
352e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // available. The system behaves as if Discard() is immediately called
353e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // whenever the buffer is posted. If ignore is set to true while a buffer is
354e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // pending, it will act as if Discard() was also called.
355e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // This returns zero or a negative unix error code.
356e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int SetIgnore(bool ignore);
357e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
358e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
359e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  friend BASE;
360e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
361e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit BufferConsumer(LocalChannelHandle channel);
36252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
36352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // Local state transition helpers.
36452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
36552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int LocalRelease(const DvrNativeBufferMetadata* meta,
36652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka                   const LocalHandle& release_fence);
367e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
368e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
369e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace dvr
370e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
371e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
372e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#endif  // ANDROID_DVR_BUFFER_HUB_CLIENT_H_
373