blob: 8a490d9983a3c27a4a0092bbb9c025847eb05876 [file] [log] [blame]
#ifndef ANDROID_DVR_BUFFER_HUB_BASE_H_
#define ANDROID_DVR_BUFFER_HUB_BASE_H_
#include <vector>
#include <private/dvr/bufferhub_rpc.h>
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 <typename T>
using Status = pdx::Status<T>;
// 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<LocalChannelHandle> 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<int> GetEventMask(int events) {
if (auto* client_channel = GetChannel()) {
return client_channel->GetEventMask(events);
} else {
return pdx::ErrorStatus(EINVAL);
}
}
std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
if (auto* client_channel = GetChannel()) {
return client_channel->GetEventSources();
} else {
return {};
}
}
native_handle_t* native_handle() const {
return const_cast<native_handle_t*>(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<uint32_t>* buffer_state_ = nullptr;
std::atomic<uint32_t>* fence_state_ = nullptr;
std::atomic<uint32_t>* 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_