#ifndef ANDROID_DVR_BUFFER_HUB_BASE_H_ #define ANDROID_DVR_BUFFER_HUB_BASE_H_ #include #include namespace android { namespace dvr { // Base class of two types of BufferHub clients: dvr::ProducerBuffer and // dvr::ConsumerBuffer. class BufferHubBase : public pdx::Client { public: using LocalHandle = pdx::LocalHandle; using LocalChannelHandle = pdx::LocalChannelHandle; template using Status = pdx::Status; // Create a new consumer channel that is attached to the producer. Returns // a file descriptor for the new channel or a negative error code. Status CreateConsumer(); // Gets a blob buffer that was created with ProducerBuffer::CreateBlob. // Locking and Unlocking is handled internally. There's no need to Unlock // after calling this method. int GetBlobReadWritePointer(size_t size, void** addr); // Returns a dup'd file descriptor for accessing the blob shared memory. The // caller takes ownership of the file descriptor and must close it or pass on // ownership. Some GPU API extensions can take file descriptors to bind shared // memory gralloc buffers to GPU buffer objects. LocalHandle GetBlobFd() const { // Current GPU vendor puts the buffer allocation in one FD. If we change GPU // vendors and this is the wrong fd, late-latching and EDS will very clearly // stop working and we will need to correct this. The alternative is to use // a GL context in the pose service to allocate this buffer or to use the // ION API directly instead of gralloc. return LocalHandle(dup(native_handle()->data[0])); } using Client::event_fd; Status GetEventMask(int events) { if (auto* client_channel = GetChannel()) { return client_channel->GetEventMask(events); } else { return pdx::ErrorStatus(EINVAL); } } std::vector GetEventSources() const { if (auto* client_channel = GetChannel()) { return client_channel->GetEventSources(); } else { return {}; } } native_handle_t* native_handle() const { return const_cast(buffer_.handle()); } IonBuffer* buffer() { return &buffer_; } const IonBuffer* buffer() const { return &buffer_; } // Gets ID of the buffer client. All BufferHub clients derived from the same // buffer in bufferhubd share the same buffer id. int id() const { return id_; } // Gets the channel id of the buffer client. Each BufferHub client has its // system unique channel id. int cid() const { return cid_; } // Returns the buffer buffer state. uint32_t buffer_state() { return buffer_state_->load(std::memory_order_acquire); }; // Returns whether the buffer is already released by all current clients. bool is_released() { return (buffer_state() & active_clients_bit_mask_->load(std::memory_order_acquire)) == 0; } // A state mask which is unique to a buffer hub client among all its siblings // sharing the same concrete graphic buffer. uint32_t client_state_mask() const { return client_state_mask_; } // The following methods return settings of the first buffer. Currently, // it is only possible to create multi-buffer BufferHubBases with the same // settings. uint32_t width() const { return buffer_.width(); } uint32_t height() const { return buffer_.height(); } uint32_t stride() const { return buffer_.stride(); } uint32_t format() const { return buffer_.format(); } uint32_t usage() const { return buffer_.usage(); } uint32_t layer_count() const { return buffer_.layer_count(); } uint64_t GetQueueIndex() const { return metadata_header_->queueIndex; } void SetQueueIndex(uint64_t index) { metadata_header_->queueIndex = index; } protected: explicit BufferHubBase(LocalChannelHandle channel); explicit BufferHubBase(const std::string& endpoint_path); virtual ~BufferHubBase(); // Initialization helper. int ImportBuffer(); // Check invalid metadata operation. Returns 0 if requested metadata is valid. int CheckMetadata(size_t user_metadata_size) const; // Send out the new fence by updating the shared fence (shared_release_fence // for producer and shared_acquire_fence for consumer). Note that during this // should only be used in LocalPost() or LocalRelease, and the shared fence // shouldn't be poll'ed by the other end. int UpdateSharedFence(const LocalHandle& new_fence, const LocalHandle& shared_fence); // Locks the area specified by (x, y, width, height) for a specific usage. If // the usage is software then |addr| will be updated to point to the address // of the buffer in virtual memory. The caller should only access/modify the // pixels in the specified area. anything else is undefined behavior. int Lock(int usage, int x, int y, int width, int height, void** addr); // Must be called after Lock() when the caller has finished changing the // buffer. int Unlock(); // IonBuffer that is shared between bufferhubd, producer, and consumers. size_t metadata_buf_size_{0}; size_t user_metadata_size_{0}; BufferHubDefs::MetadataHeader* metadata_header_ = nullptr; void* user_metadata_ptr_ = nullptr; std::atomic* buffer_state_ = nullptr; std::atomic* fence_state_ = nullptr; std::atomic* active_clients_bit_mask_ = nullptr; LocalHandle shared_acquire_fence_; LocalHandle shared_release_fence_; // A local fence fd that holds the ownership of the fence fd on Post (for // producer) and Release (for consumer). LocalHandle pending_fence_fd_; private: BufferHubBase(const BufferHubBase&) = delete; void operator=(const BufferHubBase&) = delete; // Global id for the buffer that is consistent across processes. It is meant // for logging and debugging purposes only and should not be used for lookup // or any other functional purpose as a security precaution. int id_; // Channel id. int cid_; // Client bit mask which indicates the locations of this client object in the // buffer_state_. uint32_t client_state_mask_{0U}; IonBuffer buffer_; IonBuffer metadata_buffer_; }; } // namespace dvr } // namespace android #endif // ANDROID_DVR_BUFFER_HUB_BASE_H_