blob: 83e9255240f4931e773dfa547f0a6abb52a56ae6 [file] [log] [blame]
Alex Vakulenkoe4eec202017-01-27 14:41:04 -08001#ifndef ANDROID_DVR_BUFFER_HUB_CLIENT_H_
2#define ANDROID_DVR_BUFFER_HUB_CLIENT_H_
3
4#include <hardware/gralloc.h>
5#include <pdx/channel_handle.h>
6#include <pdx/client.h>
7#include <pdx/file_handle.h>
8#include <pdx/status.h>
9
10#include <vector>
11
12#include <private/dvr/ion_buffer.h>
13
14namespace android {
15namespace dvr {
16
17class BufferHubBuffer : public pdx::Client {
18 public:
19 using LocalHandle = pdx::LocalHandle;
20 using LocalChannelHandle = pdx::LocalChannelHandle;
21 template <typename T>
22 using Status = pdx::Status<T>;
23
24 // Create a new consumer channel that is attached to the producer. Returns
25 // a file descriptor for the new channel or a negative error code.
26 Status<LocalChannelHandle> CreateConsumer();
27
28 // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
29 int Poll(int timeout_ms);
30
31 // Locks the area specified by (x, y, width, height) for a specific usage. If
32 // the usage is software then |addr| will be updated to point to the address
33 // of the buffer in virtual memory. The caller should only access/modify the
34 // pixels in the specified area. anything else is undefined behavior.
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -070035 int Lock(int usage, int x, int y, int width, int height, void** addr);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080036
37 // Must be called after Lock() when the caller has finished changing the
38 // buffer.
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -070039 int Unlock();
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080040
41 // Gets a blob buffer that was created with BufferProducer::CreateBlob.
42 // Locking and Unlocking is handled internally. There's no need to Unlock
43 // after calling this method.
44 int GetBlobReadWritePointer(size_t size, void** addr);
45
46 // Gets a blob buffer that was created with BufferProducer::CreateBlob.
47 // Locking and Unlocking is handled internally. There's no need to Unlock
48 // after calling this method.
49 int GetBlobReadOnlyPointer(size_t size, void** addr);
50
51 // Returns a dup'd file descriptor for accessing the blob shared memory. The
52 // caller takes ownership of the file descriptor and must close it or pass on
53 // ownership. Some GPU API extensions can take file descriptors to bind shared
54 // memory gralloc buffers to GPU buffer objects.
55 LocalHandle GetBlobFd() const {
56 // Current GPU vendor puts the buffer allocation in one FD. If we change GPU
57 // vendors and this is the wrong fd, late-latching and EDS will very clearly
58 // stop working and we will need to correct this. The alternative is to use
59 // a GL context in the pose service to allocate this buffer or to use the
60 // ION API directly instead of gralloc.
61 return LocalHandle(dup(native_handle()->data[0]));
62 }
63
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -070064 // Get up to |max_fds_count| file descriptors for accessing the blob shared
65 // memory. |fds_count| will contain the actual number of file descriptors.
66 void GetBlobFds(int* fds, size_t* fds_count, size_t max_fds_count) const;
67
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080068 using Client::event_fd;
Corey Tabaka3079cb72017-01-19 15:07:26 -080069
70 Status<int> GetEventMask(int events) {
71 if (auto* client_channel = GetChannel()) {
72 return client_channel->GetEventMask(events);
73 } else {
74 return pdx::ErrorStatus(EINVAL);
75 }
76 }
77
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080078 native_handle_t* native_handle() const {
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -070079 return const_cast<native_handle_t*>(buffer_.handle());
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080080 }
81
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -070082 IonBuffer* buffer() { return &buffer_; }
83 const IonBuffer* buffer() const { return &buffer_; }
Corey Tabaka2655e1c2017-04-04 11:07:05 -070084
Alex Vakulenkoe4eec202017-01-27 14:41:04 -080085 int id() const { return id_; }
86
87 // The following methods return settings of the first buffer. Currently,
88 // it is only possible to create multi-buffer BufferHubBuffers with the same
89 // settings.
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -070090 uint32_t width() const { return buffer_.width(); }
91 uint32_t height() const { return buffer_.height(); }
92 uint32_t stride() const { return buffer_.stride(); }
93 uint32_t format() const { return buffer_.format(); }
94 uint32_t usage() const { return buffer_.usage(); }
95 uint32_t layer_count() const { return buffer_.layer_count(); }
Jiwen 'Steve' Cai044963e2017-05-01 22:43:21 -070096
Corey Tabakaec971362017-05-05 18:14:54 +000097 // TODO(b/37881101) Clean up producer/consumer usage.
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -070098 uint64_t producer_usage() const { return buffer_.usage(); }
99 uint64_t consumer_usage() const { return buffer_.usage(); }
Corey Tabakaec971362017-05-05 18:14:54 +0000100
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800101 protected:
102 explicit BufferHubBuffer(LocalChannelHandle channel);
103 explicit BufferHubBuffer(const std::string& endpoint_path);
104 virtual ~BufferHubBuffer();
105
106 // Initialization helper.
107 int ImportBuffer();
108
109 private:
110 BufferHubBuffer(const BufferHubBuffer&) = delete;
111 void operator=(const BufferHubBuffer&) = delete;
112
113 // Global id for the buffer that is consistent across processes. It is meant
114 // for logging and debugging purposes only and should not be used for lookup
115 // or any other functional purpose as a security precaution.
116 int id_;
117
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700118 IonBuffer buffer_;
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800119};
120
121// This represents a writable buffer. Calling Post notifies all clients and
122// makes the buffer read-only. Call Gain to acquire write access. A buffer
123// may have many consumers.
124//
125// The user of BufferProducer is responsible with making sure that the Post() is
126// done with the correct metadata type and size. The user is also responsible
127// for making sure that remote ends (BufferConsumers) are also using the correct
128// metadata when acquiring the buffer. The API guarantees that a Post() with a
129// metadata of wrong size will fail. However, it currently does not do any
130// type checking.
131// The API also assumes that metadata is a serializable type (plain old data).
132class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
133 public:
134 // Create a buffer designed to hold arbitrary bytes that can be read and
135 // written from CPU, GPU and DSP. The buffer is mapped uncached so that CPU
136 // reads and writes are predictable.
137 static std::unique_ptr<BufferProducer> CreateUncachedBlob(size_t size);
138
139 // Creates a persistent uncached buffer with the given name and access.
140 static std::unique_ptr<BufferProducer> CreatePersistentUncachedBlob(
141 const std::string& name, int user_id, int group_id, size_t size);
142
143 // Imports a bufferhub producer channel, assuming ownership of its handle.
144 static std::unique_ptr<BufferProducer> Import(LocalChannelHandle channel);
145 static std::unique_ptr<BufferProducer> Import(
146 Status<LocalChannelHandle> status);
147
148 // Post this buffer, passing |ready_fence| to the consumers. The bytes in
149 // |meta| are passed unaltered to the consumers. The producer must not modify
150 // the buffer until it is re-gained.
151 // This returns zero or a negative unix error code.
152 int Post(const LocalHandle& ready_fence, const void* meta,
153 size_t meta_size_bytes);
154
155 template <typename Meta,
156 typename = typename std::enable_if<std::is_void<Meta>::value>::type>
157 int Post(const LocalHandle& ready_fence) {
158 return Post(ready_fence, nullptr, 0);
159 }
Corey Tabaka2655e1c2017-04-04 11:07:05 -0700160 template <typename Meta, typename = typename std::enable_if<
161 !std::is_void<Meta>::value>::type>
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800162 int Post(const LocalHandle& ready_fence, const Meta& meta) {
163 return Post(ready_fence, &meta, sizeof(meta));
164 }
165
166 // Attempt to re-gain the buffer for writing. If |release_fence| is valid, it
167 // must be waited on before using the buffer. If it is not valid then the
168 // buffer is free for immediate use. This call will only succeed if the buffer
169 // is in the released state.
170 // This returns zero or a negative unix error code.
171 int Gain(LocalHandle* release_fence);
172
173 // Asynchronously marks a released buffer as gained. This method is similar to
174 // the synchronous version above, except that it does not wait for BufferHub
175 // to acknowledge success or failure, nor does it transfer a release fence to
176 // the client. This version may be used in situations where a release fence is
177 // not needed. Because of the asynchronous nature of the underlying message,
178 // no error is returned if this method is called when the buffer is in an
179 // incorrect state. Returns zero if sending the message succeeded, or a
180 // negative errno code otherwise.
181 int GainAsync();
182
183 // Attaches the producer to |name| so that it becomes a persistent buffer that
184 // may be retrieved by name at a later time. This may be used in cases where a
185 // shared memory buffer should persist across the life of the producer process
186 // (i.e. the buffer may be held by clients across a service restart). The
187 // buffer may be associated with a user and/or group id to restrict access to
188 // the buffer. If user_id or group_id is -1 then checks for the respective id
189 // are disabled. If user_id or group_id is 0 then the respective id of the
190 // calling process is used instead.
191 int MakePersistent(const std::string& name, int user_id, int group_id);
192
193 // Removes the persistence of the producer.
194 int RemovePersistence();
195
196 private:
197 friend BASE;
198
199 // Constructors are automatically exposed through BufferProducer::Create(...)
200 // static template methods inherited from ClientBase, which take the same
201 // arguments as the constructors.
202
203 // Constructs a buffer with the given geometry and parameters.
Corey Tabakacd52dd92017-04-07 18:03:57 -0700204 BufferProducer(uint32_t width, uint32_t height, uint32_t format,
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700205 uint32_t usage, size_t metadata_size = 0);
Corey Tabakaec971362017-05-05 18:14:54 +0000206 BufferProducer(uint32_t width, uint32_t height, uint32_t format,
207 uint64_t producer_usage, uint64_t consumer_usage,
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700208 size_t metadata_size);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800209
210 // Constructs a persistent buffer with the given geometry and parameters and
211 // binds it to |name| in one shot. If a persistent buffer with the same name
212 // and settings already exists and matches the given geometry and parameters,
213 // that buffer is connected to this client instead of creating a new buffer.
214 // If the name matches but the geometry or settings do not match then
215 // construction fails and BufferProducer::Create() returns nullptr.
216 //
217 // Access to the persistent buffer may be restricted by |user_id| and/or
218 // |group_id|; these settings are established only when the buffer is first
219 // created and cannot be changed. A user or group id of -1 disables checks for
220 // that respective id. A user or group id of 0 is substituted with the
221 // effective user or group id of the calling process.
Corey Tabakacd52dd92017-04-07 18:03:57 -0700222 BufferProducer(const std::string& name, int user_id, int group_id,
223 uint32_t width, uint32_t height, uint32_t format,
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700224 uint32_t usage, size_t metadata_size = 0);
Corey Tabakaec971362017-05-05 18:14:54 +0000225 BufferProducer(const std::string& name, int user_id, int group_id,
226 uint32_t width, uint32_t height, uint32_t format,
227 uint64_t producer_usage, uint64_t consumer_usage,
Hendrik Wagenaar4d3590f2017-05-06 22:36:04 -0700228 size_t meta_size_bytes);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800229
230 // Constructs a blob (flat) buffer with the given usage flags.
Corey Tabakaec971362017-05-05 18:14:54 +0000231 BufferProducer(uint32_t usage, size_t size);
232 BufferProducer(uint64_t producer_usage, uint64_t consumer_usage, size_t size);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800233
234 // Constructs a persistent blob (flat) buffer and binds it to |name|.
Corey Tabakacd52dd92017-04-07 18:03:57 -0700235 BufferProducer(const std::string& name, int user_id, int group_id,
Corey Tabakaec971362017-05-05 18:14:54 +0000236 uint32_t usage, size_t size);
237 BufferProducer(const std::string& name, int user_id, int group_id,
238 uint64_t producer_usage, uint64_t consumer_usage, size_t size);
Alex Vakulenkoe4eec202017-01-27 14:41:04 -0800239
240 // Constructs a channel to persistent buffer by name only. The buffer must
241 // have been previously created or made persistent.
242 explicit BufferProducer(const std::string& name);
243
244 // Imports the given file handle to a producer channel, taking ownership.
245 explicit BufferProducer(LocalChannelHandle channel);
246};
247
248// This is a connection to a producer buffer, which can be located in another
249// application. When that buffer is Post()ed, this fd will be signaled and
250// Acquire allows read access. The user is responsible for making sure that
251// Acquire is called with the correct metadata structure. The only guarantee the
252// API currently provides is that an Acquire() with metadata of the wrong size
253// will fail.
254class BufferConsumer : public pdx::ClientBase<BufferConsumer, BufferHubBuffer> {
255 public:
256 // This call assumes ownership of |fd|.
257 static std::unique_ptr<BufferConsumer> Import(LocalChannelHandle channel);
258 static std::unique_ptr<BufferConsumer> Import(
259 Status<LocalChannelHandle> status);
260
261 // Attempt to retrieve a post event from buffer hub. If successful,
262 // |ready_fence| will be set to a fence to wait on until the buffer is ready.
263 // This call will only succeed after the fd is signalled. This call may be
264 // performed as an alternative to the Acquire() with metadata. In such cases
265 // the metadata is not read.
266 //
267 // This returns zero or negative unix error code.
268 int Acquire(LocalHandle* ready_fence);
269
270 // Attempt to retrieve a post event from buffer hub. If successful,
271 // |ready_fence| is set to a fence signaling that the contents of the buffer
272 // are available. This call will only succeed if the buffer is in the posted
273 // state.
274 // Returns zero on success, or a negative errno code otherwise.
275 int Acquire(LocalHandle* ready_fence, void* meta, size_t meta_size_bytes);
276
277 // Attempt to retrieve a post event from buffer hub. If successful,
278 // |ready_fence| is set to a fence to wait on until the buffer is ready. This
279 // call will only succeed after the fd is signaled. This returns zero or a
280 // negative unix error code.
281 template <typename Meta>
282 int Acquire(LocalHandle* ready_fence, Meta* meta) {
283 return Acquire(ready_fence, meta, sizeof(*meta));
284 }
285
286 // This should be called after a successful Acquire call. If the fence is
287 // valid the fence determines the buffer usage, otherwise the buffer is
288 // released immediately.
289 // This returns zero or a negative unix error code.
290 int Release(const LocalHandle& release_fence);
291
292 // Asynchronously releases a buffer. Similar to the synchronous version above,
293 // except that it does not wait for BufferHub to reply with success or error,
294 // nor does it transfer a release fence. This version may be used in
295 // situations where a release fence is not needed. Because of the asynchronous
296 // nature of the underlying message, no error is returned if this method is
297 // called when the buffer is in an incorrect state. Returns zero if sending
298 // the message succeeded, or a negative errno code otherwise.
299 int ReleaseAsync();
300
301 // May be called after or instead of Acquire to indicate that the consumer
302 // does not need to access the buffer this cycle. This returns zero or a
303 // negative unix error code.
304 int Discard();
305
306 // When set, this consumer is no longer notified when this buffer is
307 // available. The system behaves as if Discard() is immediately called
308 // whenever the buffer is posted. If ignore is set to true while a buffer is
309 // pending, it will act as if Discard() was also called.
310 // This returns zero or a negative unix error code.
311 int SetIgnore(bool ignore);
312
313 private:
314 friend BASE;
315
316 explicit BufferConsumer(LocalChannelHandle channel);
317};
318
319} // namespace dvr
320} // namespace android
321
322#endif // ANDROID_DVR_BUFFER_HUB_CLIENT_H_