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