Add DaydreamVR native libraries and services
Upstreaming the main VR system components from master-dreamos-dev
into goog/master.
Bug: None
Test: `m -j32` succeeds. Sailfish boots and basic_vr sample app works
Change-Id: I853015872afc443aecee10411ef2d6b79184d051
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
new file mode 100644
index 0000000..b6ff5b6
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -0,0 +1,313 @@
+#ifndef ANDROID_DVR_BUFFER_HUB_CLIENT_H_
+#define ANDROID_DVR_BUFFER_HUB_CLIENT_H_
+
+#include <hardware/gralloc.h>
+#include <pdx/channel_handle.h>
+#include <pdx/client.h>
+#include <pdx/file_handle.h>
+#include <pdx/status.h>
+
+#include <vector>
+
+#include <private/dvr/ion_buffer.h>
+
+namespace android {
+namespace dvr {
+
+class BufferHubBuffer : 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();
+
+ // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
+ int Poll(int timeout_ms);
+
+ // 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,
+ size_t index);
+
+ // Must be called after Lock() when the caller has finished changing the
+ // buffer.
+ int Unlock(size_t index);
+
+ // Helper for when index is 0.
+ int Lock(int usage, int x, int y, int width, int height, void** addr) {
+ return Lock(usage, x, y, width, height, addr, 0);
+ }
+
+ // Helper for when index is 0.
+ int Unlock() { return Unlock(0); }
+
+ // Gets a blob buffer that was created with BufferProducer::CreateBlob.
+ // Locking and Unlocking is handled internally. There's no need to Unlock
+ // after calling this method.
+ int GetBlobReadWritePointer(size_t size, void** addr);
+
+ // Gets a blob buffer that was created with BufferProducer::CreateBlob.
+ // Locking and Unlocking is handled internally. There's no need to Unlock
+ // after calling this method.
+ int GetBlobReadOnlyPointer(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;
+ native_handle_t* native_handle() const {
+ return const_cast<native_handle_t*>(slices_[0].handle());
+ }
+ // If index is greater than or equal to slice_count(), the result is
+ // undefined.
+ native_handle_t* native_handle(size_t index) const {
+ return const_cast<native_handle_t*>(slices_[index].handle());
+ }
+
+ IonBuffer* buffer() { return &slices_[0]; }
+ // If index is greater than or equal to slice_count(), the result is
+ // undefined.
+ IonBuffer* slice(size_t index) { return &slices_[index]; }
+
+ int slice_count() const { return static_cast<int>(slices_.size()); }
+ int id() const { return id_; }
+
+ // The following methods return settings of the first buffer. Currently,
+ // it is only possible to create multi-buffer BufferHubBuffers with the same
+ // settings.
+ int width() const { return slices_[0].width(); }
+ int height() const { return slices_[0].height(); }
+ int stride() const { return slices_[0].stride(); }
+ int format() const { return slices_[0].format(); }
+ int usage() const { return slices_[0].usage(); }
+
+ protected:
+ explicit BufferHubBuffer(LocalChannelHandle channel);
+ explicit BufferHubBuffer(const std::string& endpoint_path);
+ virtual ~BufferHubBuffer();
+
+ // Initialization helper.
+ int ImportBuffer();
+
+ private:
+ BufferHubBuffer(const BufferHubBuffer&) = delete;
+ void operator=(const BufferHubBuffer&) = 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_;
+
+ // A BufferHubBuffer may contain multiple slices of IonBuffers with same
+ // configurations.
+ std::vector<IonBuffer> slices_;
+};
+
+// This represents a writable buffer. Calling Post notifies all clients and
+// makes the buffer read-only. Call Gain to acquire write access. A buffer
+// may have many consumers.
+//
+// The user of BufferProducer is responsible with making sure that the Post() is
+// done with the correct metadata type and size. The user is also responsible
+// for making sure that remote ends (BufferConsumers) are also using the correct
+// metadata when acquiring the buffer. The API guarantees that a Post() with a
+// metadata of wrong size will fail. However, it currently does not do any
+// type checking.
+// The API also assumes that metadata is a serializable type (plain old data).
+class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
+ public:
+ // Create a buffer designed to hold arbitrary bytes that can be read and
+ // written from CPU, GPU and DSP. The buffer is mapped uncached so that CPU
+ // reads and writes are predictable.
+ static std::unique_ptr<BufferProducer> CreateUncachedBlob(size_t size);
+
+ // Creates a persistent uncached buffer with the given name and access.
+ static std::unique_ptr<BufferProducer> CreatePersistentUncachedBlob(
+ const std::string& name, int user_id, int group_id, size_t size);
+
+ // Imports a bufferhub producer channel, assuming ownership of its handle.
+ static std::unique_ptr<BufferProducer> Import(LocalChannelHandle channel);
+ static std::unique_ptr<BufferProducer> Import(
+ Status<LocalChannelHandle> status);
+
+ // Post this buffer, passing |ready_fence| to the consumers. The bytes in
+ // |meta| are passed unaltered to the consumers. The producer must not modify
+ // the buffer until it is re-gained.
+ // This returns zero or a negative unix error code.
+ int Post(const LocalHandle& ready_fence, const void* meta,
+ size_t meta_size_bytes);
+
+ template <typename Meta,
+ typename = typename std::enable_if<std::is_void<Meta>::value>::type>
+ int Post(const LocalHandle& ready_fence) {
+ return Post(ready_fence, nullptr, 0);
+ }
+ template <typename Meta, typename = typename std::enable_if<
+ !std::is_void<Meta>::value>::type>
+ int Post(const LocalHandle& ready_fence, const Meta& meta) {
+ return Post(ready_fence, &meta, sizeof(meta));
+ }
+
+ // Attempt to re-gain the buffer for writing. If |release_fence| is valid, it
+ // must be waited on before using the buffer. If it is not valid then the
+ // buffer is free for immediate use. This call will only succeed if the buffer
+ // is in the released state.
+ // This returns zero or a negative unix error code.
+ int Gain(LocalHandle* release_fence);
+
+ // Asynchronously marks a released buffer as gained. This method is similar to
+ // the synchronous version above, except that it does not wait for BufferHub
+ // to acknowledge success or failure, nor does it transfer a release fence to
+ // the client. This version may be used in situations where a release fence is
+ // not needed. Because of the asynchronous nature of the underlying message,
+ // no error is returned if this method is called when the buffer is in an
+ // incorrect state. Returns zero if sending the message succeeded, or a
+ // negative errno code otherwise.
+ int GainAsync();
+
+ // Attaches the producer to |name| so that it becomes a persistent buffer that
+ // may be retrieved by name at a later time. This may be used in cases where a
+ // shared memory buffer should persist across the life of the producer process
+ // (i.e. the buffer may be held by clients across a service restart). The
+ // buffer may be associated with a user and/or group id to restrict access to
+ // the buffer. If user_id or group_id is -1 then checks for the respective id
+ // are disabled. If user_id or group_id is 0 then the respective id of the
+ // calling process is used instead.
+ int MakePersistent(const std::string& name, int user_id, int group_id);
+
+ // Removes the persistence of the producer.
+ int RemovePersistence();
+
+ private:
+ friend BASE;
+
+ // Constructors are automatically exposed through BufferProducer::Create(...)
+ // static template methods inherited from ClientBase, which take the same
+ // arguments as the constructors.
+
+ // Constructs a buffer with the given geometry and parameters.
+ BufferProducer(int width, int height, int format, int usage,
+ size_t metadata_size = 0, size_t slice_count = 1);
+
+ // Constructs a persistent buffer with the given geometry and parameters and
+ // binds it to |name| in one shot. If a persistent buffer with the same name
+ // and settings already exists and matches the given geometry and parameters,
+ // that buffer is connected to this client instead of creating a new buffer.
+ // If the name matches but the geometry or settings do not match then
+ // construction fails and BufferProducer::Create() returns nullptr.
+ //
+ // Access to the persistent buffer may be restricted by |user_id| and/or
+ // |group_id|; these settings are established only when the buffer is first
+ // created and cannot be changed. A user or group id of -1 disables checks for
+ // that respective id. A user or group id of 0 is substituted with the
+ // effective user or group id of the calling process.
+ BufferProducer(const std::string& name, int user_id, int group_id, int width,
+ int height, int format, int usage, size_t metadata_size = 0,
+ size_t slice_count = 1);
+
+ // Constructs a blob (flat) buffer with the given usage flags.
+ BufferProducer(int usage, size_t size);
+
+ // Constructs a persistent blob (flat) buffer and binds it to |name|.
+ BufferProducer(const std::string& name, int user_id, int group_id, int usage,
+ size_t size);
+
+ // Constructs a channel to persistent buffer by name only. The buffer must
+ // have been previously created or made persistent.
+ explicit BufferProducer(const std::string& name);
+
+ // Imports the given file handle to a producer channel, taking ownership.
+ explicit BufferProducer(LocalChannelHandle channel);
+};
+
+// This is a connection to a producer buffer, which can be located in another
+// application. When that buffer is Post()ed, this fd will be signaled and
+// Acquire allows read access. The user is responsible for making sure that
+// Acquire is called with the correct metadata structure. The only guarantee the
+// API currently provides is that an Acquire() with metadata of the wrong size
+// will fail.
+class BufferConsumer : public pdx::ClientBase<BufferConsumer, BufferHubBuffer> {
+ public:
+ // This call assumes ownership of |fd|.
+ static std::unique_ptr<BufferConsumer> Import(LocalChannelHandle channel);
+ static std::unique_ptr<BufferConsumer> Import(
+ Status<LocalChannelHandle> status);
+
+ // Attempt to retrieve a post event from buffer hub. If successful,
+ // |ready_fence| will be set to a fence to wait on until the buffer is ready.
+ // This call will only succeed after the fd is signalled. This call may be
+ // performed as an alternative to the Acquire() with metadata. In such cases
+ // the metadata is not read.
+ //
+ // This returns zero or negative unix error code.
+ int Acquire(LocalHandle* ready_fence);
+
+ // Attempt to retrieve a post event from buffer hub. If successful,
+ // |ready_fence| is set to a fence signaling that the contents of the buffer
+ // are available. This call will only succeed if the buffer is in the posted
+ // state.
+ // Returns zero on success, or a negative errno code otherwise.
+ int Acquire(LocalHandle* ready_fence, void* meta, size_t meta_size_bytes);
+
+ // Attempt to retrieve a post event from buffer hub. If successful,
+ // |ready_fence| is set to a fence to wait on until the buffer is ready. This
+ // call will only succeed after the fd is signaled. This returns zero or a
+ // negative unix error code.
+ template <typename Meta>
+ int Acquire(LocalHandle* ready_fence, Meta* meta) {
+ return Acquire(ready_fence, meta, sizeof(*meta));
+ }
+
+ // This should be called after a successful Acquire call. If the fence is
+ // valid the fence determines the buffer usage, otherwise the buffer is
+ // released immediately.
+ // This returns zero or a negative unix error code.
+ int Release(const LocalHandle& release_fence);
+
+ // Asynchronously releases a buffer. Similar to the synchronous version above,
+ // except that it does not wait for BufferHub to reply with success or error,
+ // nor does it transfer a release fence. This version may be used in
+ // situations where a release fence is not needed. Because of the asynchronous
+ // nature of the underlying message, no error is returned if this method is
+ // called when the buffer is in an incorrect state. Returns zero if sending
+ // the message succeeded, or a negative errno code otherwise.
+ int ReleaseAsync();
+
+ // May be called after or instead of Acquire to indicate that the consumer
+ // does not need to access the buffer this cycle. This returns zero or a
+ // negative unix error code.
+ int Discard();
+
+ // When set, this consumer is no longer notified when this buffer is
+ // available. The system behaves as if Discard() is immediately called
+ // whenever the buffer is posted. If ignore is set to true while a buffer is
+ // pending, it will act as if Discard() was also called.
+ // This returns zero or a negative unix error code.
+ int SetIgnore(bool ignore);
+
+ private:
+ friend BASE;
+
+ explicit BufferConsumer(LocalChannelHandle channel);
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_BUFFER_HUB_CLIENT_H_