1 #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 14 #include "bufferhub_rpc.h" 15 16 namespace android { 17 namespace dvr { 18 19 class BufferHubClient : public pdx::Client { 20 public: 21 BufferHubClient(); 22 explicit BufferHubClient(pdx::LocalChannelHandle channel_handle); 23 24 bool IsValid() const; 25 pdx::LocalChannelHandle TakeChannelHandle(); 26 27 using pdx::Client::Close; 28 using pdx::Client::GetChannel; 29 using pdx::Client::InvokeRemoteMethod; 30 using pdx::Client::IsConnected; 31 using pdx::Client::event_fd; 32 }; 33 34 class BufferHubBuffer : public pdx::Client { 35 public: 36 using LocalHandle = pdx::LocalHandle; 37 using LocalChannelHandle = pdx::LocalChannelHandle; 38 template <typename T> 39 using Status = pdx::Status<T>; 40 41 // Create a new consumer channel that is attached to the producer. Returns 42 // a file descriptor for the new channel or a negative error code. 43 Status<LocalChannelHandle> CreateConsumer(); 44 45 // Polls the fd for |timeout_ms| milliseconds (-1 for infinity). 46 int Poll(int timeout_ms); 47 48 // Locks the area specified by (x, y, width, height) for a specific usage. If 49 // the usage is software then |addr| will be updated to point to the address 50 // of the buffer in virtual memory. The caller should only access/modify the 51 // pixels in the specified area. anything else is undefined behavior. 52 int Lock(int usage, int x, int y, int width, int height, void** addr); 53 54 // Must be called after Lock() when the caller has finished changing the 55 // buffer. 56 int Unlock(); 57 58 // Gets a blob buffer that was created with BufferProducer::CreateBlob. 59 // Locking and Unlocking is handled internally. There's no need to Unlock 60 // after calling this method. 61 int GetBlobReadWritePointer(size_t size, void** addr); 62 63 // Gets a blob buffer that was created with BufferProducer::CreateBlob. 64 // Locking and Unlocking is handled internally. There's no need to Unlock 65 // after calling this method. 66 int GetBlobReadOnlyPointer(size_t size, void** addr); 67 68 // Returns a dup'd file descriptor for accessing the blob shared memory. The 69 // caller takes ownership of the file descriptor and must close it or pass on 70 // ownership. Some GPU API extensions can take file descriptors to bind shared 71 // memory gralloc buffers to GPU buffer objects. 72 LocalHandle GetBlobFd() const { 73 // Current GPU vendor puts the buffer allocation in one FD. If we change GPU 74 // vendors and this is the wrong fd, late-latching and EDS will very clearly 75 // stop working and we will need to correct this. The alternative is to use 76 // a GL context in the pose service to allocate this buffer or to use the 77 // ION API directly instead of gralloc. 78 return LocalHandle(dup(native_handle()->data[0])); 79 } 80 81 // Get up to |max_fds_count| file descriptors for accessing the blob shared 82 // memory. |fds_count| will contain the actual number of file descriptors. 83 void GetBlobFds(int* fds, size_t* fds_count, size_t max_fds_count) const; 84 85 using Client::event_fd; 86 87 Status<int> GetEventMask(int events) { 88 if (auto* client_channel = GetChannel()) { 89 return client_channel->GetEventMask(events); 90 } else { 91 return pdx::ErrorStatus(EINVAL); 92 } 93 } 94 95 std::vector<pdx::ClientChannel::EventSource> GetEventSources() const { 96 if (auto* client_channel = GetChannel()) { 97 return client_channel->GetEventSources(); 98 } else { 99 return {}; 100 } 101 } 102 103 native_handle_t* native_handle() const { 104 return const_cast<native_handle_t*>(buffer_.handle()); 105 } 106 107 IonBuffer* buffer() { return &buffer_; } 108 const IonBuffer* buffer() const { return &buffer_; } 109 110 int id() const { return id_; } 111 112 // Returns the buffer buffer state. 113 uint64_t buffer_state() { return buffer_state_->load(); }; 114 115 // A state mask which is unique to a buffer hub client among all its siblings 116 // sharing the same concrete graphic buffer. 117 uint64_t buffer_state_bit() const { return buffer_state_bit_; } 118 119 // The following methods return settings of the first buffer. Currently, 120 // it is only possible to create multi-buffer BufferHubBuffers with the same 121 // settings. 122 uint32_t width() const { return buffer_.width(); } 123 uint32_t height() const { return buffer_.height(); } 124 uint32_t stride() const { return buffer_.stride(); } 125 uint32_t format() const { return buffer_.format(); } 126 uint32_t usage() const { return buffer_.usage(); } 127 uint32_t layer_count() const { return buffer_.layer_count(); } 128 129 uint64_t GetQueueIndex() const { return metadata_header_->queue_index; } 130 void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; } 131 132 protected: 133 explicit BufferHubBuffer(LocalChannelHandle channel); 134 explicit BufferHubBuffer(const std::string& endpoint_path); 135 virtual ~BufferHubBuffer(); 136 137 // Initialization helper. 138 int ImportBuffer(); 139 140 // Check invalid metadata operation. Returns 0 if requested metadata is valid. 141 int CheckMetadata(size_t user_metadata_size) const; 142 143 // Send out the new fence by updating the shared fence (shared_release_fence 144 // for producer and shared_acquire_fence for consumer). Note that during this 145 // should only be used in LocalPost() or LocalRelease, and the shared fence 146 // shouldn't be poll'ed by the other end. 147 int UpdateSharedFence(const LocalHandle& new_fence, 148 const LocalHandle& shared_fence); 149 150 // IonBuffer that is shared between bufferhubd, producer, and consumers. 151 size_t metadata_buf_size_{0}; 152 size_t user_metadata_size_{0}; 153 BufferHubDefs::MetadataHeader* metadata_header_{nullptr}; 154 void* user_metadata_ptr_{nullptr}; 155 std::atomic<uint64_t>* buffer_state_{nullptr}; 156 std::atomic<uint64_t>* fence_state_{nullptr}; 157 158 LocalHandle shared_acquire_fence_; 159 LocalHandle shared_release_fence_; 160 161 // A local fence fd that holds the ownership of the fence fd on Post (for 162 // producer) and Release (for consumer). 163 LocalHandle pending_fence_fd_; 164 165 private: 166 BufferHubBuffer(const BufferHubBuffer&) = delete; 167 void operator=(const BufferHubBuffer&) = delete; 168 169 // Global id for the buffer that is consistent across processes. It is meant 170 // for logging and debugging purposes only and should not be used for lookup 171 // or any other functional purpose as a security precaution. 172 int id_; 173 uint64_t buffer_state_bit_{0ULL}; 174 IonBuffer buffer_; 175 IonBuffer metadata_buffer_; 176 }; 177 178 // This represents a writable buffer. Calling Post notifies all clients and 179 // makes the buffer read-only. Call Gain to acquire write access. A buffer 180 // may have many consumers. 181 // 182 // The user of BufferProducer is responsible with making sure that the Post() is 183 // done with the correct metadata type and size. The user is also responsible 184 // for making sure that remote ends (BufferConsumers) are also using the correct 185 // metadata when acquiring the buffer. The API guarantees that a Post() with a 186 // metadata of wrong size will fail. However, it currently does not do any 187 // type checking. 188 // The API also assumes that metadata is a serializable type (plain old data). 189 class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> { 190 public: 191 // Imports a bufferhub producer channel, assuming ownership of its handle. 192 static std::unique_ptr<BufferProducer> Import(LocalChannelHandle channel); 193 static std::unique_ptr<BufferProducer> Import( 194 Status<LocalChannelHandle> status); 195 196 // Asynchronously posts a buffer. The fence and metadata are passed to 197 // consumer via shared fd and shared memory. 198 int PostAsync(const DvrNativeBufferMetadata* meta, 199 const LocalHandle& ready_fence); 200 201 // Post this buffer, passing |ready_fence| to the consumers. The bytes in 202 // |meta| are passed unaltered to the consumers. The producer must not modify 203 // the buffer until it is re-gained. 204 // This returns zero or a negative unix error code. 205 int Post(const LocalHandle& ready_fence, const void* meta, 206 size_t user_metadata_size); 207 208 template <typename Meta, 209 typename = typename std::enable_if<std::is_void<Meta>::value>::type> 210 int Post(const LocalHandle& ready_fence) { 211 return Post(ready_fence, nullptr, 0); 212 } 213 template <typename Meta, typename = typename std::enable_if< 214 !std::is_void<Meta>::value>::type> 215 int Post(const LocalHandle& ready_fence, const Meta& meta) { 216 return Post(ready_fence, &meta, sizeof(meta)); 217 } 218 219 // Attempt to re-gain the buffer for writing. If |release_fence| is valid, it 220 // must be waited on before using the buffer. If it is not valid then the 221 // buffer is free for immediate use. This call will only succeed if the buffer 222 // is in the released state. 223 // This returns zero or a negative unix error code. 224 int Gain(LocalHandle* release_fence); 225 int GainAsync(); 226 227 // Asynchronously marks a released buffer as gained. This method is similar to 228 // the synchronous version above, except that it does not wait for BufferHub 229 // to acknowledge success or failure. Because of the asynchronous nature of 230 // the underlying message, no error is returned if this method is called when 231 // the buffer is in an incorrect state. Returns zero if sending the message 232 // succeeded, or a negative errno code if local error check fails. 233 int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence); 234 235 // Detaches a ProducerBuffer from an existing producer/consumer set. Can only 236 // be called when a producer buffer has exclusive access to the buffer (i.e. 237 // in the gain'ed state). On the successful return of the IPC call, a new 238 // LocalChannelHandle representing a detached buffer will be returned and all 239 // existing producer and consumer channels will be closed. Further IPCs 240 // towards those channels will return error. 241 Status<LocalChannelHandle> Detach(); 242 243 private: 244 friend BASE; 245 246 // Constructors are automatically exposed through BufferProducer::Create(...) 247 // static template methods inherited from ClientBase, which take the same 248 // arguments as the constructors. 249 250 // Constructs a buffer with the given geometry and parameters. 251 BufferProducer(uint32_t width, uint32_t height, uint32_t format, 252 uint64_t usage, size_t metadata_size = 0); 253 254 // Constructs a blob (flat) buffer with the given usage flags. 255 BufferProducer(uint64_t usage, size_t size); 256 257 // Imports the given file handle to a producer channel, taking ownership. 258 explicit BufferProducer(LocalChannelHandle channel); 259 260 // Local state transition helpers. 261 int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence); 262 int LocalPost(const DvrNativeBufferMetadata* meta, 263 const LocalHandle& ready_fence); 264 }; 265 266 // This is a connection to a producer buffer, which can be located in another 267 // application. When that buffer is Post()ed, this fd will be signaled and 268 // Acquire allows read access. The user is responsible for making sure that 269 // Acquire is called with the correct metadata structure. The only guarantee the 270 // API currently provides is that an Acquire() with metadata of the wrong size 271 // will fail. 272 class BufferConsumer : public pdx::ClientBase<BufferConsumer, BufferHubBuffer> { 273 public: 274 // This call assumes ownership of |fd|. 275 static std::unique_ptr<BufferConsumer> Import(LocalChannelHandle channel); 276 static std::unique_ptr<BufferConsumer> Import( 277 Status<LocalChannelHandle> status); 278 279 // Attempt to retrieve a post event from buffer hub. If successful, 280 // |ready_fence| will be set to a fence to wait on until the buffer is ready. 281 // This call will only succeed after the fd is signalled. This call may be 282 // performed as an alternative to the Acquire() with metadata. In such cases 283 // the metadata is not read. 284 // 285 // This returns zero or negative unix error code. 286 int Acquire(LocalHandle* ready_fence); 287 288 // Attempt to retrieve a post event from buffer hub. If successful, 289 // |ready_fence| is set to a fence signaling that the contents of the buffer 290 // are available. This call will only succeed if the buffer is in the posted 291 // state. 292 // Returns zero on success, or a negative errno code otherwise. 293 int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size); 294 295 // Attempt to retrieve a post event from buffer hub. If successful, 296 // |ready_fence| is set to a fence to wait on until the buffer is ready. This 297 // call will only succeed after the fd is signaled. This returns zero or a 298 // negative unix error code. 299 template <typename Meta> 300 int Acquire(LocalHandle* ready_fence, Meta* meta) { 301 return Acquire(ready_fence, meta, sizeof(*meta)); 302 } 303 304 // Asynchronously acquires a bufer. 305 int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence); 306 307 // This should be called after a successful Acquire call. If the fence is 308 // valid the fence determines the buffer usage, otherwise the buffer is 309 // released immediately. 310 // This returns zero or a negative unix error code. 311 int Release(const LocalHandle& release_fence); 312 int ReleaseAsync(); 313 314 // Asynchronously releases a buffer. Similar to the synchronous version above, 315 // except that it does not wait for BufferHub to reply with success or error. 316 // The fence and metadata are passed to consumer via shared fd and shared 317 // memory. 318 int ReleaseAsync(const DvrNativeBufferMetadata* meta, 319 const LocalHandle& release_fence); 320 321 // May be called after or instead of Acquire to indicate that the consumer 322 // does not need to access the buffer this cycle. This returns zero or a 323 // negative unix error code. 324 int Discard(); 325 326 // When set, this consumer is no longer notified when this buffer is 327 // available. The system behaves as if Discard() is immediately called 328 // whenever the buffer is posted. If ignore is set to true while a buffer is 329 // pending, it will act as if Discard() was also called. 330 // This returns zero or a negative unix error code. 331 int SetIgnore(bool ignore); 332 333 private: 334 friend BASE; 335 336 explicit BufferConsumer(LocalChannelHandle channel); 337 338 // Local state transition helpers. 339 int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence); 340 int LocalRelease(const DvrNativeBufferMetadata* meta, 341 const LocalHandle& release_fence); 342 }; 343 344 } // namespace dvr 345 } // namespace android 346 347 #endif // ANDROID_DVR_BUFFER_HUB_CLIENT_H_ 348