Adopt the use of shared buffers.
Bug: 37001948
Test: Make system image
Change-Id: I032574f250e0f0fe7768af649730406e24d853db
diff --git a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
index 236e3aa..f2e5034 100644
--- a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
+++ b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
@@ -174,8 +174,6 @@
//
// There must be at least |MemorySize(record_count)| bytes of space already
// allocated at |mmap|. The ring does not take ownership.
- //
- // Use this function for dynamically sized rings.
static BroadcastRing Create(void* mmap, size_t mmap_size,
uint32_t record_count) {
BroadcastRing ring(mmap);
@@ -188,12 +186,11 @@
//
// There must be at least |MemorySize()| bytes of space already allocated at
// |mmap|. The ring does not take ownership.
- //
- // Use this function for statically sized rings.
static BroadcastRing Create(void* mmap, size_t mmap_size) {
- static_assert(Traits::kUseStaticRecordCount,
- "Wrong Create() function called for dynamic record count");
- return Create(mmap, mmap_size, Traits::kStaticRecordCount);
+ return Create(mmap, mmap_size,
+ Traits::kUseStaticRecordCount
+ ? Traits::kStaticRecordCount
+ : BroadcastRing::GetRecordCount(mmap_size));
}
// Imports an existing ring at |mmap|.
@@ -233,6 +230,30 @@
return MemorySize(Traits::kStaticRecordCount);
}
+ static uint32_t NextPowerOf2(uint32_t n) {
+ if (n == 0)
+ return 0;
+ n -= 1;
+ n |= n >> 16;
+ n |= n >> 8;
+ n |= n >> 4;
+ n |= n >> 2;
+ n |= n >> 1;
+ return n + 1;
+ }
+
+ // Gets the biggest power of 2 record count that can fit into this mmap.
+ //
+ // The header size has been taken into account.
+ static uint32_t GetRecordCount(size_t mmap_size) {
+ if (mmap_size <= sizeof(Header)) {
+ return 0;
+ }
+ uint32_t count =
+ static_cast<uint32_t>((mmap_size - sizeof(Header)) / sizeof(Record));
+ return IsPowerOfTwo(count) ? count : (NextPowerOf2(count) / 2);
+ }
+
// Writes a record to the ring.
//
// The oldest record is overwritten unless the ring is not already full.
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index c0c7e2f..e3ab7fa 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -17,6 +17,7 @@
"display_manager_client.cpp",
"display_protocol.cpp",
"vsync_client.cpp",
+ "shared_buffer_helpers.cpp",
]
localIncludeFiles = [
@@ -39,7 +40,7 @@
"libdvrcommon",
"libbufferhubqueue",
"libbufferhub",
- "libvrsensor",
+ "libbroadcastring",
"libpdx_default_transport",
]
diff --git a/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
new file mode 100644
index 0000000..249f410
--- /dev/null
+++ b/libs/vr/libdisplay/include/private/dvr/shared_buffer_helpers.h
@@ -0,0 +1,138 @@
+#ifndef ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+#define ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
+
+#include <assert.h>
+#include <tuple>
+
+#include <libbroadcastring/broadcast_ring.h>
+#include <private/dvr/display_client.h>
+
+namespace android {
+namespace dvr {
+
+// The buffer usage type for mapped shared buffers.
+enum class CPUUsageMode { READ_OFTEN, READ_RARELY, WRITE_OFTEN, WRITE_RARELY };
+
+// Holds the memory for the mapped shared buffer. Unlocks and releases the
+// underlying IonBuffer in destructor.
+class CPUMappedBuffer {
+ public:
+ // This constructor will create a display client and get the buffer from it.
+ CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode);
+
+ // If you already have the IonBuffer, use this. It will take ownership.
+ CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode);
+
+ // Use this if you do not want to take ownership.
+ CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode);
+
+ ~CPUMappedBuffer();
+
+ // Getters.
+ size_t Size() const { return size_; }
+ void* Address() const { return address_; }
+ bool IsMapped() const { return Address() != nullptr; }
+
+ // Attempt mapping this buffer to the CPU addressable space.
+ // This will create a display client and see if the buffer exists.
+ // If the buffer has not been setup yet, you will need to try again later.
+ void TryMapping();
+
+ protected:
+ // The memory area if we managed to map it.
+ size_t size_ = 0;
+ void* address_ = nullptr;
+
+ // If we are polling the display client, the buffer key here.
+ DvrGlobalBufferKey buffer_key_;
+
+ // If we just own the IonBuffer outright, it's here.
+ std::unique_ptr<IonBuffer> owned_buffer_ = nullptr;
+
+ // If we do not own the IonBuffer, it's here
+ IonBuffer* buffer_ = nullptr;
+
+ // The usage mode.
+ CPUUsageMode usage_mode_ = CPUUsageMode::READ_OFTEN;
+};
+
+// Represents a broadcast ring inside a mapped shared memory buffer.
+// If has the same set of constructors as CPUMappedBuffer.
+// The template argument is the concrete BroadcastRing class that this buffer
+// holds.
+template <class RingType>
+class CPUMappedBroadcastRing : public CPUMappedBuffer {
+ public:
+ CPUMappedBroadcastRing(DvrGlobalBufferKey key, CPUUsageMode mode)
+ : CPUMappedBuffer(key, mode) {}
+
+ CPUMappedBroadcastRing(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode)
+ : CPUMappedBuffer(std::move(buffer), mode) {}
+
+ CPUMappedBroadcastRing(IonBuffer* buffer, CPUUsageMode mode)
+ : CPUMappedBuffer(buffer, mode) {}
+
+ // Helper function for publishing records in the ring.
+ void Publish(const typename RingType::Record& record) {
+ assert((usage_mode_ == CPUUsageMode::WRITE_OFTEN) ||
+ (usage_mode_ == CPUUsageMode::WRITE_RARELY));
+
+ auto ring = Ring();
+ if (ring) {
+ ring->Put(record);
+ }
+ }
+
+ // Helper function for getting records from the ring.
+ // Returns true if we were able to retrieve the latest.
+ bool GetNewest(typename RingType::Record* record) {
+ assert((usage_mode_ == CPUUsageMode::READ_OFTEN) ||
+ (usage_mode_ == CPUUsageMode::READ_RARELY));
+
+ auto ring = Ring();
+ if (ring) {
+ return ring->GetNewest(&sequence_, record);
+ }
+
+ return false;
+ }
+
+ // Try obtaining the ring. If the named buffer has not been created yet, it
+ // will return nullptr.
+ RingType* Ring() {
+ if (IsMapped() == false) {
+ TryMapping();
+
+ if (IsMapped()) {
+ switch (usage_mode_) {
+ case CPUUsageMode::READ_OFTEN:
+ case CPUUsageMode::READ_RARELY: {
+ RingType ring;
+ bool import_ok;
+ std::tie(ring, import_ok) = RingType::Import(address_, size_);
+ if (import_ok) {
+ ring_ = std::make_unique<RingType>(ring);
+ }
+ } break;
+ case CPUUsageMode::WRITE_OFTEN:
+ case CPUUsageMode::WRITE_RARELY:
+ ring_ =
+ std::make_unique<RingType>(RingType::Create(address_, size_));
+ break;
+ }
+ }
+ }
+
+ return ring_.get();
+ }
+
+ protected:
+ std::unique_ptr<RingType> ring_ = nullptr;
+
+ uint32_t sequence_ = 0;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
diff --git a/libs/vr/libdisplay/shared_buffer_helpers.cpp b/libs/vr/libdisplay/shared_buffer_helpers.cpp
new file mode 100644
index 0000000..00bad88
--- /dev/null
+++ b/libs/vr/libdisplay/shared_buffer_helpers.cpp
@@ -0,0 +1,84 @@
+#include <private/dvr/shared_buffer_helpers.h>
+
+namespace android {
+namespace dvr {
+
+CPUMappedBuffer::CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode)
+ : buffer_key_(key), usage_mode_(mode) {
+ TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer,
+ CPUUsageMode mode)
+ : owned_buffer_(std::move(buffer)),
+ buffer_(owned_buffer_.get()),
+ usage_mode_(mode) {
+ TryMapping();
+}
+
+CPUMappedBuffer::CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode)
+ : buffer_(buffer), usage_mode_(mode) {
+ TryMapping();
+}
+
+CPUMappedBuffer::~CPUMappedBuffer() {
+ if (IsMapped()) {
+ buffer_->Unlock();
+ }
+}
+
+void CPUMappedBuffer::TryMapping() {
+ // Do we have an IonBuffer for this shared memory object?
+ if (buffer_ == nullptr) {
+ // Create a display client and get the buffer.
+ // TODO(okana): We might want to throttle this.
+ auto display_client = display::DisplayClient::Create();
+ if (display_client) {
+ auto get_result = display_client->GetGlobalBuffer(buffer_key_);
+ if (get_result.ok()) {
+ owned_buffer_ = get_result.take();
+ buffer_ = owned_buffer_.get();
+ } else {
+ ALOGW("Could not get named buffer from pose service : %s(%d)",
+ get_result.GetErrorMessage().c_str(), get_result.error());
+ }
+ } else {
+ ALOGE("Unable to create display client for shared buffer access");
+ }
+ }
+
+ if (buffer_) {
+ auto usage = buffer_->usage() & ~GRALLOC_USAGE_SW_READ_MASK &
+ ~GRALLOC_USAGE_SW_WRITE_MASK;
+
+ // Figure out the usage bits.
+ switch (usage_mode_) {
+ case CPUUsageMode::READ_OFTEN:
+ usage |= GRALLOC_USAGE_SW_READ_OFTEN;
+ break;
+ case CPUUsageMode::READ_RARELY:
+ usage |= GRALLOC_USAGE_SW_READ_RARELY;
+ break;
+ case CPUUsageMode::WRITE_OFTEN:
+ usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
+ break;
+ case CPUUsageMode::WRITE_RARELY:
+ usage |= GRALLOC_USAGE_SW_WRITE_RARELY;
+ break;
+ }
+
+ int width = static_cast<int>(buffer_->width());
+ int height = 1;
+ const auto ret = buffer_->Lock(usage, 0, 0, width, height, &address_);
+
+ if (ret < 0 || !address_) {
+ ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, address_);
+ buffer_->Unlock();
+ } else {
+ size_ = width;
+ }
+ }
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index fa78b1c..2b4ebbe 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -34,10 +34,11 @@
]
static_libs = [
+ "libbroadcastring",
"libbufferhub",
"libbufferhubqueue",
- "libdisplay",
"libvrsensor",
+ "libdisplay",
"libvirtualtouchpadclient",
"libvr_hwc-impl",
"libvr_hwc-binder",
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index ef2c975..06f89da 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -18,7 +18,7 @@
typedef uint64_t DvrSurfaceUpdateFlags;
typedef struct DvrDisplayManager DvrDisplayManager;
typedef struct DvrSurfaceState DvrSurfaceState;
-typedef struct DvrPose DvrPose;
+typedef struct DvrPoseClient DvrPoseClient;
typedef struct DvrVSyncClient DvrVSyncClient;
typedef struct DvrVirtualTouchpad DvrVirtualTouchpad;
@@ -182,14 +182,15 @@
uint32_t* next_vsync_count);
// pose_client.h
-typedef DvrPose* (*DvrPoseCreatePtr)(void);
-typedef void (*DvrPoseDestroyPtr)(DvrPose* client);
-typedef int (*DvrPoseGetPtr)(DvrPose* client, uint32_t vsync_count,
- DvrPoseAsync* out_pose);
-typedef uint32_t (*DvrPoseGetVsyncCountPtr)(DvrPose* client);
-typedef int (*DvrPoseGetControllerPtr)(DvrPose* client, int32_t controller_id,
- uint32_t vsync_count,
- DvrPoseAsync* out_pose);
+typedef DvrPoseClient* (*DvrPoseClientCreatePtr)(void);
+typedef void (*DvrPoseClientDestroyPtr)(DvrPoseClient* client);
+typedef int (*DvrPoseClientGetPtr)(DvrPoseClient* client, uint32_t vsync_count,
+ DvrPoseAsync* out_pose);
+typedef uint32_t (*DvrPoseClientGetVsyncCountPtr)(DvrPoseClient* client);
+typedef int (*DvrPoseClientGetControllerPtr)(DvrPoseClient* client,
+ int32_t controller_id,
+ uint32_t vsync_count,
+ DvrPoseAsync* out_pose);
// virtual_touchpad_client.h
typedef DvrVirtualTouchpad* (*DvrVirtualTouchpadCreatePtr)(void);
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index 30d0a65..441df4f 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -89,11 +89,11 @@
DVR_V1_API_ENTRY(GetGlobalBuffer);
// Pose client
-DVR_V1_API_ENTRY(PoseCreate);
-DVR_V1_API_ENTRY(PoseDestroy);
-DVR_V1_API_ENTRY(PoseGet);
-DVR_V1_API_ENTRY(PoseGetVsyncCount);
-DVR_V1_API_ENTRY(PoseGetController);
+DVR_V1_API_ENTRY(PoseClientCreate);
+DVR_V1_API_ENTRY(PoseClientDestroy);
+DVR_V1_API_ENTRY(PoseClientGet);
+DVR_V1_API_ENTRY(PoseClientGetVsyncCount);
+DVR_V1_API_ENTRY(PoseClientGetController);
// Virtual touchpad client
DVR_V1_API_ENTRY(VirtualTouchpadCreate);
diff --git a/libs/vr/libdvr/include/dvr/dvr_pose.h b/libs/vr/libdvr/include/dvr/dvr_pose.h
new file mode 100644
index 0000000..a7e83c9
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_pose.h
@@ -0,0 +1,79 @@
+#ifndef ANDROID_DVR_PUBLIC_POSE_H_
+#define ANDROID_DVR_PUBLIC_POSE_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+#ifdef __ARM_NEON
+#include <arm_neon.h>
+#else
+#ifndef __FLOAT32X4T_86
+#define __FLOAT32X4T_86
+typedef float float32x4_t __attribute__((__vector_size__(16)));
+#endif
+#endif
+
+// Represents an estimated pose, accessed asynchronously through a shared ring
+// buffer. No assumptions should be made about the data in padding space.
+// The size of this struct is 128 bytes.
+typedef struct __attribute__((packed, aligned(16))) DvrPoseAsync {
+ // Left eye head-from-start orientation quaternion x,y,z,w.
+ float32x4_t orientation;
+ // Left eye head-from-start position x,y,z,pad in meters.
+ float32x4_t position;
+ // Right eye head-from-start orientation quaternion x,y,z,w.
+ float32x4_t right_orientation;
+ // Right eye head-from-start position x,y,z,pad in meters.
+ float32x4_t right_position;
+ // Start-space angular velocity x,y,z,pad in radians per second.
+ float32x4_t angular_velocity;
+ // Start-space positional velocity x,y,z,pad in meters per second.
+ float32x4_t velocity;
+ // Timestamp of when this pose is predicted for, typically halfway through
+ // scanout.
+ int64_t timestamp_ns;
+ // Bitmask of DVR_POSE_FLAG_* constants that apply to this pose.
+ //
+ // If DVR_POSE_FLAG_VALID is not set, the pose is indeterminate.
+ uint64_t flags;
+ // Reserved padding to 128 bytes.
+ uint8_t pad[16];
+} DvrPoseAsync;
+
+enum {
+ DVR_POSE_FLAG_VALID = (1UL << 0), // This pose is valid.
+ DVR_POSE_FLAG_HEAD = (1UL << 1), // This pose is the head.
+ DVR_POSE_FLAG_CONTROLLER = (1UL << 2), // This pose is a controller.
+};
+
+// Represents a sensor pose sample.
+typedef struct __attribute__((packed, aligned(16))) DvrPose {
+ // Head-from-start orientation quaternion x,y,z,w.
+ float32x4_t orientation;
+
+ // The angular velocity where the x,y,z is the rotation axis and the
+ // magnitude is the radians / second in the same coordinate frame as
+ // orientation.
+ float32x4_t angular_velocity;
+
+ // Head-from-start position x,y,z,pad in meters.
+ float32x4_t position;
+
+ // In meters / second in the same coordinate frame as position.
+ float32x4_t velocity;
+
+ // In meters / second ^ 2 in the same coordinate frame as position.
+ float32x4_t acceleration;
+
+ // Timestamp for the measurement in nanoseconds.
+ int64_t timestamp_ns;
+
+ // Padding to 96 bytes so the size is a multiple of 16.
+ uint8_t padding[8];
+} DvrPose;
+
+__END_DECLS
+
+#endif // ANDROID_DVR_PUBLIC_POSE_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
new file mode 100644
index 0000000..ce17f0c
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_shared_buffers.h
@@ -0,0 +1,102 @@
+#ifndef ANDROID_DVR_SHARED_BUFFERS_H_
+#define ANDROID_DVR_SHARED_BUFFERS_H_
+
+#include <dvr/dvr_pose.h>
+#include <dvr/dvr_vrflinger_config.h>
+#include <dvr/dvr_vsync.h>
+#include <libbroadcastring/broadcast_ring.h>
+
+// This header is shared by VrCore and Android and must be kept in sync.
+namespace android {
+namespace dvr {
+
+// Increment when the layout for the buffers change.
+constexpr uint32_t kSharedBufferLayoutVersion = 1;
+
+// Note: These buffers will be mapped from various system processes as well
+// as VrCore and the application processes in a r/w manner.
+//
+// Therefore it is possible for the application to mess with the contents of
+// these buffers.
+//
+// While using them, assume garbage memory: Your logic must not crash or lead
+// to execution of unsafe code as a function of the contents of these buffers.
+
+// Sanity check for basic type sizes.
+static_assert(sizeof(DvrPoseAsync) == 128, "Unexpected size for DvrPoseAsync");
+static_assert(sizeof(DvrPose) == 96, "Unexpected size for DvrPose");
+static_assert(sizeof(DvrVsync) == 32, "Unexpected size for DvrVsync");
+
+// A helper class that provides compile time sized traits for the BroadcastRing.
+template <class DvrType, size_t StaticCount>
+class DvrRingBufferTraits {
+ public:
+ using Record = DvrType;
+ static constexpr bool kUseStaticRecordSize = false;
+ static constexpr uint32_t kStaticRecordCount = StaticCount;
+ static constexpr int kMaxReservedRecords = 1;
+ static constexpr int kMinAvailableRecords = 1;
+};
+
+// Traits classes.
+using DvrPoseTraits = DvrRingBufferTraits<DvrPose, 0>;
+using DvrVsyncTraits = DvrRingBufferTraits<DvrVsync, 2>;
+using DvrVrFlingerConfigTraits = DvrRingBufferTraits<DvrVrFlingerConfig, 2>;
+
+// The broadcast ring classes that will expose the data.
+using DvrPoseRing = BroadcastRing<DvrPose, DvrPoseTraits>;
+using DvrVsyncRing = BroadcastRing<DvrVsync, DvrVsyncTraits>;
+using DvrVrFlingerConfigRing =
+ BroadcastRing<DvrVrFlingerConfig, DvrVrFlingerConfigTraits>;
+
+// This is a shared memory buffer for passing pose data estimated at vsyncs.
+//
+// This will be primarily used for late latching and EDS where we bind this
+// buffer in a shader and extract the right vsync-predicted pose.
+struct __attribute__((packed, aligned(16))) DvrVsyncPoseBuffer {
+ enum : int {
+ // The number vsync predicted poses to keep in the ring buffer.
+ // Must be a power of 2.
+ kSize = 8,
+ kIndexMask = kSize - 1,
+
+ // The number of vsyncs (from the current vsync) we predict in vsync buffer.
+ // The other poses are left alone.
+ kMinFutureCount = 4
+ };
+
+ // The vsync predicted poses.
+ // The pose for the vsync n is:
+ // vsync_poses[n % kSize]
+ //
+ // This buffer is unsynchronized: It is possible to get torn reads as the
+ // sensor service updates the predictions as new sensor measurements come
+ // in. In particular, it is possible to get the position and an updated
+ // orientation while reading.
+ DvrPoseAsync vsync_poses[kSize];
+
+ // The latest sensor pose for GPU usage.
+ DvrPose current_pose;
+
+ // Current vsync_count (where sensord is writing poses from).
+ uint32_t vsync_count;
+
+ // For 16 byte alignment.
+ uint8_t padding[12];
+};
+
+static_assert(sizeof(DvrVsyncPoseBuffer) == 1136,
+ "Unexpected size for DvrVsyncPoseBuffer");
+
+// The keys for the dvr global buffers.
+enum DvrGlobalBuffers : int32_t {
+ kVsyncPoseBuffer = 1,
+ kVsyncBuffer = 2,
+ kSensorPoseBuffer = 3,
+ kVrFlingerConfigBufferKey = 4
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_SHARED_BUFFERS_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h b/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h
new file mode 100644
index 0000000..cfe9d62
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_vrflinger_config.h
@@ -0,0 +1,30 @@
+#ifndef ANDROID_DVR_VRFLINGER_CONFIG_H
+#define ANDROID_DVR_VRFLINGER_CONFIG_H
+
+// This header is shared by VrCore and Android and must be kept in sync.
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// This is a shared memory buffer for passing config data from VrCore to
+// libvrflinger in SurfaceFlinger.
+struct DvrVrFlingerConfig {
+ // Offset before vsync to submit frames to hardware composer.
+ int frame_post_offset_ns{4000000};
+
+ // If the number of pending fences goes over this count at the point when we
+ // are about to submit a new frame to HWC, we will drop the frame. This
+ // should be a signal that the display driver has begun queuing frames. Note
+ // that with smart displays (with RAM), the fence is signaled earlier than
+ // the next vsync, at the point when the DMA to the display completes.
+ // Currently we use a smart display and the EDS timing coincides with zero
+ // pending fences, so this is 0.
+ size_t allowed_pending_fence_count{0};
+
+ // New fields should always be added to the end for backwards compat.
+};
+
+__END_DECLS
+
+#endif // ANDROID_DVR_VRFLINGER_CONFIG_H
diff --git a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config_buffer.h b/libs/vr/libdvr/include/dvr/dvr_vrflinger_config_buffer.h
deleted file mode 100644
index 108c78b..0000000
--- a/libs/vr/libdvr/include/dvr/dvr_vrflinger_config_buffer.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef ANDROID_DVR_VRFLINGER_CONFIG_BUFFER_H
-#define ANDROID_DVR_VRFLINGER_CONFIG_BUFFER_H
-
-#include <libbroadcastring/broadcast_ring.h>
-
-// This header is shared by VrCore and Android and must be kept in sync.
-
-namespace android {
-namespace dvr {
-
-// Increment when the layout for the buffers change.
-constexpr uint32_t kSharedConfigBufferLayoutVersion = 1;
-
-// This is a shared memory buffer for passing config data from VrCore to
-// libvrflinger in SurfaceFlinger.
-struct DvrVrFlingerConfigBuffer {
- // Offset before vsync to submit frames to hardware composer.
- int frame_post_offset_ns{4000000};
-
- // If the number of pending fences goes over this count at the point when we
- // are about to submit a new frame to HWC, we will drop the frame. This
- // should be a signal that the display driver has begun queuing frames. Note
- // that with smart displays (with RAM), the fence is signaled earlier than
- // the next vsync, at the point when the DMA to the display completes.
- // Currently we use a smart display and the EDS timing coincides with zero
- // pending fences, so this is 0.
- size_t allowed_pending_fence_count{0};
-
- // New fields should always be added to the end for backwards compat.
-};
-
-class DvrVrFlingerConfigBufferTraits {
- public:
- using Record = DvrVrFlingerConfigBuffer;
- static constexpr bool kUseStaticRecordSize = false;
- static constexpr uint32_t kStaticRecordCount = 2;
- static constexpr int kMaxReservedRecords = 1;
- static constexpr int kMinAvailableRecords = 1;
-};
-
-// The broadcast ring classes that will expose the data.
-using DvrVrFlingerConfigRing =
- BroadcastRing<DvrVrFlingerConfigBuffer, DvrVrFlingerConfigBufferTraits>;
-
-// Common buffers.
-constexpr int kVrFlingerConfigBufferKey = 5;
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_VRFLINGER_CONFIG_BUFFER_H
diff --git a/libs/vr/libdvr/include/dvr/dvr_vsync.h b/libs/vr/libdvr/include/dvr/dvr_vsync.h
index 1eea3d9..87fdf31 100644
--- a/libs/vr/libdvr/include/dvr/dvr_vsync.h
+++ b/libs/vr/libdvr/include/dvr/dvr_vsync.h
@@ -8,6 +8,27 @@
typedef struct DvrVSyncClient DvrVSyncClient;
+// Represents a vsync sample. The size of this struct is 32 bytes.
+typedef struct __attribute__((packed, aligned(16))) DvrVsync {
+ // The timestamp for the last vsync in nanoseconds.
+ uint64_t vsync_timestamp_ns;
+
+ // The index of the last vsync.
+ uint32_t vsync_count;
+
+ // Scan out for the left eye = vsync_timestamp_ns + vsync_left_eye_offset_ns.
+ int32_t vsync_left_eye_offset_ns;
+
+ // Scan out for the right eye = vsync_timestamp_ns + vsync_right_eye_offset_ns
+ int32_t vsync_right_eye_offset_ns;
+
+ // The period of a vsync in nanoseconds.
+ uint32_t vsync_period_ns;
+
+ // Padding to 32 bytes so the size is a multiple of 16.
+ uint8_t padding[8];
+} DvrVsync;
+
// Creates a new client to the system vsync service.
int dvrVSyncClientCreate(DvrVSyncClient** client_out);
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
index cf04588..419083f 100644
--- a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -1,8 +1,9 @@
#include <android/hardware_buffer.h>
#include <dvr/dvr_buffer.h>
#include <dvr/dvr_display_manager.h>
+#include <dvr/dvr_shared_buffers.h>
#include <dvr/dvr_surface.h>
-#include <dvr/dvr_vrflinger_config_buffer.h>
+#include <dvr/dvr_vrflinger_config.h>
#include <system/graphics.h>
#include <base/logging.h>
@@ -275,7 +276,8 @@
}
TEST_F(DvrGlobalBufferTest, TestVrflingerConfigBuffer) {
- const DvrGlobalBufferKey buffer_name = kVrFlingerConfigBufferKey;
+ const DvrGlobalBufferKey buffer_name =
+ DvrGlobalBuffers::kVrFlingerConfigBufferKey;
// First delete any existing buffer so we can test the failure case.
dvrDisplayManagerDeleteGlobalBuffer(client_, buffer_name);
diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp
index 527cdbd..62aeb79 100644
--- a/libs/vr/libdvrcommon/Android.bp
+++ b/libs/vr/libdvrcommon/Android.bp
@@ -28,7 +28,7 @@
"libhardware",
]
-staticLibraries = ["libpdx_default_transport"]
+staticLibraries = ["libpdx_default_transport", "libbroadcastring"]
headerLibraries = [
"libeigen",
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 080479a..0fb2d84 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -34,6 +34,7 @@
"libdvrcommon",
"libperformance",
"libvrsensor",
+ "libbroadcastring",
"libpdx_default_transport",
"libvr_manager",
"libbroadcastring",
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 88173ca..7a78d1f 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -25,7 +25,6 @@
#include <dvr/performance_client_api.h>
#include <private/dvr/clock_ns.h>
#include <private/dvr/ion_buffer.h>
-#include <private/dvr/pose_client_internal.h>
using android::pdx::LocalHandle;
using android::pdx::rpc::EmptyVariant;
@@ -211,10 +210,6 @@
void HardwareComposer::OnPostThreadResumed() {
hwc2_hidl_->resetCommands();
- // Connect to pose service.
- pose_client_ = dvrPoseCreate();
- ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
-
// HIDL HWC seems to have an internal race condition. If we submit a frame too
// soon after turning on VSync we don't get any VSync signals. Give poor HWC
// implementations a chance to enable VSync before we continue.
@@ -243,11 +238,6 @@
}
active_layer_count_ = 0;
- if (pose_client_) {
- dvrPoseDestroy(pose_client_);
- pose_client_ = nullptr;
- }
-
EnableVsync(false);
hwc2_hidl_->resetCommands();
@@ -467,7 +457,16 @@
int HardwareComposer::OnNewGlobalBuffer(DvrGlobalBufferKey key,
IonBuffer& ion_buffer) {
- if (key == kVrFlingerConfigBufferKey) {
+ if (key == DvrGlobalBuffers::kVsyncBuffer) {
+ vsync_ring_ = std::make_unique<CPUMappedBroadcastRing<DvrVsyncRing>>(
+ &ion_buffer, CPUUsageMode::WRITE_OFTEN);
+
+ if (vsync_ring_->IsMapped() == false) {
+ return -EPERM;
+ }
+ }
+
+ if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
return MapConfigBuffer(ion_buffer);
}
@@ -475,7 +474,7 @@
}
void HardwareComposer::OnDeletedGlobalBuffer(DvrGlobalBufferKey key) {
- if (key == kVrFlingerConfigBufferKey) {
+ if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
ConfigBufferDeleted();
}
}
@@ -515,7 +514,7 @@
if (!shared_config_ring_.is_valid())
return;
// Copy from latest record in shared_config_ring_ to local copy.
- DvrVrFlingerConfigBuffer record;
+ DvrVrFlingerConfig record;
if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
post_thread_config_ = record;
}
@@ -850,16 +849,20 @@
++vsync_count_;
- if (pose_client_) {
- // Signal the pose service with vsync info.
- // Display timestamp is in the middle of scanout.
- privateDvrPoseNotifyVsync(pose_client_, vsync_count_,
- vsync_timestamp + photon_offset_ns,
- ns_per_frame, right_eye_photon_offset_ns);
- }
-
const bool layer_config_changed = UpdateLayerConfig();
+ // Publish the vsync event.
+ if (vsync_ring_) {
+ DvrVsync vsync;
+ vsync.vsync_count = vsync_count_;
+ vsync.vsync_timestamp_ns = vsync_timestamp;
+ vsync.vsync_left_eye_offset_ns = photon_offset_ns;
+ vsync.vsync_right_eye_offset_ns = right_eye_photon_offset_ns;
+ vsync.vsync_period_ns = ns_per_frame;
+
+ vsync_ring_->Publish(vsync);
+ }
+
// Signal all of the vsync clients. Because absolute time is used for the
// wakeup time below, this can take a little time if necessary.
if (vsync_callback_)
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index c182bf9..de6f9ff 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -5,6 +5,7 @@
#include "DisplayHardware/ComposerHal.h"
#include "hwc_types.h"
+#include <dvr/dvr_shared_buffers.h>
#include <hardware/gralloc.h>
#include <log/log.h>
@@ -16,11 +17,12 @@
#include <tuple>
#include <vector>
-#include <dvr/dvr_vrflinger_config_buffer.h>
-#include <dvr/pose_client.h>
+#include <dvr/dvr_vrflinger_config.h>
+#include <dvr/dvr_vsync.h>
#include <pdx/file_handle.h>
#include <pdx/rpc/variant.h>
#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/shared_buffer_helpers.h>
#include "acquired_buffer.h"
#include "display_surface.h"
@@ -446,15 +448,14 @@
// us to detect when the display driver begins queuing frames.
std::vector<pdx::LocalHandle> retire_fence_fds_;
- // Pose client for frame count notifications. Pose client predicts poses
- // out to display frame boundaries, so we need to tell it about vsyncs.
- DvrPose* pose_client_ = nullptr;
+ // If we are publishing vsync data, we will put it here.
+ std::unique_ptr<CPUMappedBroadcastRing<DvrVsyncRing>> vsync_ring_;
// Broadcast ring for receiving config data from the DisplayManager.
DvrVrFlingerConfigRing shared_config_ring_;
uint32_t shared_config_ring_sequence_{0};
// Config buffer for reading from the post thread.
- DvrVrFlingerConfigBuffer post_thread_config_;
+ DvrVrFlingerConfig post_thread_config_;
std::mutex shared_config_mutex_;
static constexpr int kPostThreadInterrupted = 1;
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index abad78b..d022adf 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -23,9 +23,11 @@
]
staticLibraries = [
+ "libdisplay",
"libbufferhub",
"libbufferhubqueue",
"libdvrcommon",
+ "libbroadcastring",
"libpdx_default_transport",
]
@@ -43,6 +45,7 @@
export_include_dirs: includeFiles,
static_libs: staticLibraries,
shared_libs: sharedLibraries,
+ header_libs: ["libdvr_headers"],
name: "libvrsensor",
}
diff --git a/libs/vr/libvrsensor/include/dvr/pose_client.h b/libs/vr/libvrsensor/include/dvr/pose_client.h
index 6802fa9..43a8e74 100644
--- a/libs/vr/libvrsensor/include/dvr/pose_client.h
+++ b/libs/vr/libvrsensor/include/dvr/pose_client.h
@@ -14,63 +14,13 @@
#include <stdbool.h>
#include <stdint.h>
+#include <dvr/dvr_pose.h>
+
#ifdef __cplusplus
extern "C" {
#endif
-typedef struct DvrPose DvrPose;
-
-// Represents the current state provided by the pose service, containing a
-// rotation and translation.
-typedef struct __attribute__((packed, aligned(8))) DvrPoseState {
- // A quaternion representing the rotation of the HMD in Start Space.
- struct __attribute__((packed)) {
- float x, y, z, w;
- } head_from_start_rotation;
- // The position of the HMD in Start Space.
- struct __attribute__((packed)) {
- float x, y, z;
- } head_from_start_translation;
- // Time in nanoseconds for the current pose.
- uint64_t timestamp_ns;
- // The rotational velocity of the HMD.
- struct __attribute__((packed)) {
- float x, y, z;
- } sensor_from_start_rotation_velocity;
-} DvrPoseState;
-
-enum {
- DVR_POSE_FLAG_VALID = (1UL << 0), // This pose is valid.
- DVR_POSE_FLAG_HEAD = (1UL << 1), // This pose is the head.
- DVR_POSE_FLAG_CONTROLLER = (1UL << 2), // This pose is a controller.
-};
-
-// Represents an estimated pose, accessed asynchronously through a shared ring
-// buffer. No assumptions should be made about the data in padding space.
-// The size of this struct is 128 bytes.
-typedef struct __attribute__((packed, aligned(16))) DvrPoseAsync {
- // Left eye head-from-start orientation quaternion x,y,z,w.
- float32x4_t orientation;
- // Left eye head-from-start translation x,y,z,pad in meters.
- float32x4_t translation;
- // Right eye head-from-start orientation quaternion x,y,z,w.
- float32x4_t right_orientation;
- // Right eye head-from-start translation x,y,z,pad in meters.
- float32x4_t right_translation;
- // Start-space angular velocity x,y,z,pad in radians per second.
- float32x4_t angular_velocity;
- // Start-space positional velocity x,y,z,pad in meters per second.
- float32x4_t velocity;
- // Timestamp of when this pose is predicted for, typically halfway through
- // scanout.
- int64_t timestamp_ns;
- // Bitmask of DVR_POSE_FLAG_* constants that apply to this pose.
- //
- // If DVR_POSE_FLAG_VALID is not set, the pose is indeterminate.
- uint64_t flags;
- // Reserved padding to 128 bytes.
- uint8_t pad[16];
-} DvrPoseAsync;
+typedef struct DvrPoseClient DvrPoseClient;
// Returned by the async pose ring buffer access API.
typedef struct DvrPoseRingBufferInfo {
@@ -120,12 +70,12 @@
// Creates a new pose client.
//
// @return Pointer to the created pose client, nullptr on failure.
-DvrPose* dvrPoseCreate();
+DvrPoseClient* dvrPoseClientCreate();
// Destroys a pose client.
//
// @param client Pointer to the pose client to be destroyed.
-void dvrPoseDestroy(DvrPose* client);
+void dvrPoseClientDestroy(DvrPoseClient* client);
// Gets the pose for the given vsync count.
//
@@ -134,10 +84,11 @@
// Typically this is the count returned by dvrGetNextVsyncCount.
// @param out_pose Struct to store pose state.
// @return Zero on success, negative error code on failure.
-int dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose);
+int dvrPoseClientGet(DvrPoseClient* client, uint32_t vsync_count,
+ DvrPoseAsync* out_pose);
// Gets the current vsync count.
-uint32_t dvrPoseGetVsyncCount(DvrPose* client);
+uint32_t dvrPoseClientGetVsyncCount(DvrPoseClient* client);
// Gets the pose for the given controller at the given vsync count.
//
@@ -147,15 +98,15 @@
// Typically this is the count returned by dvrGetNextVsyncCount.
// @param out_pose Struct to store pose state.
// @return Zero on success, negative error code on failure.
-int dvrPoseGetController(DvrPose* client, int32_t controller_id,
- uint32_t vsync_count, DvrPoseAsync* out_pose);
+int dvrPoseClientGetController(DvrPoseClient* client, int32_t controller_id,
+ uint32_t vsync_count, DvrPoseAsync* out_pose);
// Enables/disables logging for the controller fusion.
//
// @param client Pointer to the pose client.
// @param enable True starts logging, False stops.
// @return Zero on success, negative error code on failure.
-int dvrPoseLogController(DvrPose* client, bool enable);
+int dvrPoseClientLogController(DvrPoseClient* client, bool enable);
// DEPRECATED
// Polls current pose state.
@@ -163,7 +114,7 @@
// @param client Pointer to the pose client.
// @param state Struct to store polled state.
// @return Zero on success, negative error code on failure.
-int dvrPosePoll(DvrPose* client, DvrPoseState* state);
+int dvrPoseClientPoll(DvrPoseClient* client, DvrPose* state);
// Freezes the pose to the provided state.
//
@@ -174,19 +125,19 @@
// @param client Pointer to the pose client.
// @param frozen_state State pose to be frozen to.
// @return Zero on success, negative error code on failure.
-int dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state);
+int dvrPoseClientFreeze(DvrPoseClient* client, const DvrPose* frozen_state);
// Sets the pose service mode.
//
// @param mode The requested pose mode.
// @return Zero on success, negative error code on failure.
-int dvrPoseSetMode(DvrPose* client, DvrPoseMode mode);
+int dvrPoseClientSetMode(DvrPoseClient* client, DvrPoseMode mode);
// Gets the pose service mode.
//
// @param mode Return value for the current pose mode.
// @return Zero on success, negative error code on failure.
-int dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode);
+int dvrPoseClientGetMode(DvrPoseClient* client, DvrPoseMode* mode);
// Get access to the shared memory pose ring buffer.
// A future pose at vsync <current> + <offset> is accessed at index:
@@ -197,8 +148,8 @@
// |out_fd| will be set to the gralloc buffer file descriptor, which is
// required for binding this buffer for GPU use.
// Returns 0 on success.
-int dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info);
-
+int dvrPoseClientGetRingBuffer(DvrPoseClient* client,
+ DvrPoseRingBufferInfo* out_info);
#ifdef __cplusplus
} // extern "C"
diff --git a/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h b/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
index 0616d46..9603f1b 100644
--- a/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
+++ b/libs/vr/libvrsensor/include/private/dvr/pose-ipc.h
@@ -11,11 +11,8 @@
#define DVR_POSE_SERVICE_CLIENT (DVR_POSE_SERVICE_BASE "/client")
enum {
- DVR_POSE_POLL = 0,
- DVR_POSE_FREEZE,
+ DVR_POSE_FREEZE = 0,
DVR_POSE_SET_MODE,
- DVR_POSE_GET_RING_BUFFER,
- DVR_POSE_NOTIFY_VSYNC,
DVR_POSE_GET_MODE,
DVR_POSE_GET_CONTROLLER_RING_BUFFER,
DVR_POSE_LOG_CONTROLLER,
diff --git a/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h b/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
deleted file mode 100644
index 66c4c7c..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
-#define ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
-
-#include <stdint.h>
-
-#include <dvr/pose_client.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/sensor_constants.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Sensord head pose ring buffer.
-typedef struct __attribute__((packed, aligned(16))) DvrPoseRingBuffer {
- // Ring buffer always at the beginning of the structure, as consumers may
- // not have access to this parent structure definition.
- DvrPoseAsync ring[kPoseAsyncBufferTotalCount];
- // Current vsync_count (where sensord is writing poses from).
- uint32_t vsync_count;
-} DvrPoseMetadata;
-
-// Called by displayd to give vsync count info to the pose service.
-// |display_timestamp| Display timestamp is in the middle of scanout.
-// |display_period_ns| Nanos between vsyncs.
-// |right_eye_photon_offset_ns| Nanos to shift the prediction timestamp for
-// the right eye head pose (relative to the left eye prediction).
-int privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
- int64_t display_timestamp,
- int64_t display_period_ns,
- int64_t right_eye_photon_offset_ns);
-
-// Get file descriptor for access to the shared memory pose buffer. This can be
-// used with GL extensions that support shared memory buffer objects. The caller
-// takes ownership of the returned fd and must close it or pass on ownership.
-int privateDvrPoseGetRingBufferFd(DvrPose* client,
- android::pdx::LocalHandle* fd);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // ANDROID_DVR_POSE_CLIENT_INTERNAL_H_
diff --git a/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h b/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h
deleted file mode 100644
index 8fa87b3..0000000
--- a/libs/vr/libvrsensor/include/private/dvr/sensor_constants.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef ANDROID_DVR_SENSOR_CONSTANTS_H_
-#define ANDROID_DVR_SENSOR_CONSTANTS_H_
-
-namespace android {
-namespace dvr {
-
-// Number of elements in the async pose buffer.
-// Must be power of two.
-// Macro so that shader code can easily include this value.
-#define kPoseAsyncBufferTotalCount 8
-
-// Mask for accessing the current ring buffer array element:
-// index = vsync_count & kPoseAsyncBufferIndexMask
-constexpr uint32_t kPoseAsyncBufferIndexMask = kPoseAsyncBufferTotalCount - 1;
-
-// Number of pose frames including the current frame that are kept updated with
-// pose forecast data. The other poses are left their last known estimates.
-constexpr uint32_t kPoseAsyncBufferMinFutureCount = 4;
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_SENSOR_CONSTANTS_H_
diff --git a/libs/vr/libvrsensor/pose_client.cpp b/libs/vr/libvrsensor/pose_client.cpp
index 9eae3aa..2166597 100644
--- a/libs/vr/libvrsensor/pose_client.cpp
+++ b/libs/vr/libvrsensor/pose_client.cpp
@@ -1,4 +1,5 @@
#define LOG_TAG "PoseClient"
+#include <dvr/dvr_shared_buffers.h>
#include <dvr/pose_client.h>
#include <stdint.h>
@@ -8,9 +9,9 @@
#include <pdx/default_transport/client_channel_factory.h>
#include <pdx/file_handle.h>
#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/display_client.h>
#include <private/dvr/pose-ipc.h>
-#include <private/dvr/pose_client_internal.h>
-#include <private/dvr/sensor_constants.h>
+#include <private/dvr/shared_buffer_helpers.h>
using android::pdx::LocalHandle;
using android::pdx::LocalChannelHandle;
@@ -28,39 +29,44 @@
~PoseClient() override {}
// Casts C handle into an instance of this class.
- static PoseClient* FromC(DvrPose* client) {
+ static PoseClient* FromC(DvrPoseClient* client) {
return reinterpret_cast<PoseClient*>(client);
}
// Polls the pose service for the current state and stores it in *state.
// Returns zero on success, a negative error code otherwise.
- int Poll(DvrPoseState* state) {
- Transaction trans{*this};
- Status<int> status =
- trans.Send<int>(DVR_POSE_POLL, nullptr, 0, state, sizeof(*state));
- ALOGE_IF(!status, "Pose poll() failed because: %s\n",
- status.GetErrorMessage().c_str());
- return ReturnStatusOrError(status);
+ int Poll(DvrPose* state) {
+ const auto vsync_buffer = GetVsyncBuffer();
+ if (vsync_buffer) {
+ if (state) {
+ // Fill the state
+ *state = vsync_buffer->current_pose;
+ }
+ return -EINVAL;
+ }
+
+ return -EAGAIN;
}
int GetPose(uint32_t vsync_count, DvrPoseAsync* out_pose) {
- if (!mapped_pose_buffer_) {
- int ret = GetRingBuffer(nullptr);
- if (ret < 0)
- return ret;
+ const auto vsync_buffer = GetVsyncBuffer();
+ if (vsync_buffer) {
+ *out_pose =
+ vsync_buffer
+ ->vsync_poses[vsync_count & DvrVsyncPoseBuffer::kIndexMask];
+ return 0;
+ } else {
+ return -EAGAIN;
}
- *out_pose =
- mapped_pose_buffer_->ring[vsync_count & kPoseAsyncBufferIndexMask];
- return 0;
}
uint32_t GetVsyncCount() {
- if (!mapped_pose_buffer_) {
- int ret = GetRingBuffer(nullptr);
- if (ret < 0)
- return 0;
+ const auto vsync_buffer = GetVsyncBuffer();
+ if (vsync_buffer) {
+ return vsync_buffer->vsync_count;
}
- return mapped_pose_buffer_->vsync_count;
+
+ return 0;
}
int GetControllerPose(int32_t controller_id, uint32_t vsync_count,
@@ -75,7 +81,7 @@
}
*out_pose =
controllers_[controller_id]
- .mapped_pose_buffer[vsync_count & kPoseAsyncBufferIndexMask];
+ .mapped_pose_buffer[vsync_count & DvrVsyncPoseBuffer::kIndexMask];
return 0;
}
@@ -92,7 +98,7 @@
// this state until a different state is frozen or SetMode() is called with a
// different mode.
// Returns zero on success, a negative error code otherwise.
- int Freeze(const DvrPoseState& frozen_state) {
+ int Freeze(const DvrPose& frozen_state) {
Transaction trans{*this};
Status<int> status = trans.Send<int>(DVR_POSE_FREEZE, &frozen_state,
sizeof(frozen_state), nullptr, 0);
@@ -125,47 +131,18 @@
}
int GetRingBuffer(DvrPoseRingBufferInfo* out_info) {
- if (pose_buffer_.get()) {
+ // First time mapping the buffer?
+ const auto vsync_buffer = GetVsyncBuffer();
+ if (vsync_buffer) {
if (out_info) {
- GetPoseRingBufferInfo(out_info);
+ out_info->min_future_count = DvrVsyncPoseBuffer::kMinFutureCount;
+ out_info->total_count = DvrVsyncPoseBuffer::kSize;
+ out_info->buffer = vsync_buffer->vsync_poses;
}
- return 0;
+ return -EINVAL;
}
- Transaction trans{*this};
- Status<LocalChannelHandle> status =
- trans.Send<LocalChannelHandle>(DVR_POSE_GET_RING_BUFFER);
- if (!status) {
- ALOGE("Pose GetRingBuffer() failed because: %s",
- status.GetErrorMessage().c_str());
- return -status.error();
- }
-
- auto buffer = BufferConsumer::Import(status.take());
- if (!buffer) {
- ALOGE("Pose failed to import ring buffer");
- return -EIO;
- }
- void* addr = nullptr;
- int ret = buffer->GetBlobReadOnlyPointer(sizeof(DvrPoseRingBuffer), &addr);
- if (ret < 0 || !addr) {
- ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
- return -EIO;
- }
- pose_buffer_.swap(buffer);
- mapped_pose_buffer_ = static_cast<const DvrPoseRingBuffer*>(addr);
- ALOGI("Mapped pose data translation %f,%f,%f quat %f,%f,%f,%f",
- mapped_pose_buffer_->ring[0].translation[0],
- mapped_pose_buffer_->ring[0].translation[1],
- mapped_pose_buffer_->ring[0].translation[2],
- mapped_pose_buffer_->ring[0].orientation[0],
- mapped_pose_buffer_->ring[0].orientation[1],
- mapped_pose_buffer_->ring[0].orientation[2],
- mapped_pose_buffer_->ring[0].orientation[3]);
- if (out_info) {
- GetPoseRingBufferInfo(out_info);
- }
- return 0;
+ return -EAGAIN;
}
int GetControllerRingBuffer(int32_t controller_id) {
@@ -190,7 +167,7 @@
ALOGE("Pose failed to import ring buffer");
return -EIO;
}
- constexpr size_t size = kPoseAsyncBufferTotalCount * sizeof(DvrPoseAsync);
+ constexpr size_t size = DvrVsyncPoseBuffer::kSize * sizeof(DvrPoseAsync);
void* addr = nullptr;
int ret = buffer->GetBlobReadOnlyPointer(size, &addr);
if (ret < 0 || !addr) {
@@ -201,9 +178,9 @@
client_state.mapped_pose_buffer = static_cast<const DvrPoseAsync*>(addr);
ALOGI(
"Mapped controller %d pose data translation %f,%f,%f quat %f,%f,%f,%f",
- controller_id, client_state.mapped_pose_buffer[0].translation[0],
- client_state.mapped_pose_buffer[0].translation[1],
- client_state.mapped_pose_buffer[0].translation[2],
+ controller_id, client_state.mapped_pose_buffer[0].position[0],
+ client_state.mapped_pose_buffer[0].position[1],
+ client_state.mapped_pose_buffer[0].position[2],
client_state.mapped_pose_buffer[0].orientation[0],
client_state.mapped_pose_buffer[0].orientation[1],
client_state.mapped_pose_buffer[0].orientation[2],
@@ -211,32 +188,6 @@
return 0;
}
- int NotifyVsync(uint32_t vsync_count, int64_t display_timestamp,
- int64_t display_period_ns,
- int64_t right_eye_photon_offset_ns) {
- const struct iovec data[] = {
- {.iov_base = &vsync_count, .iov_len = sizeof(vsync_count)},
- {.iov_base = &display_timestamp, .iov_len = sizeof(display_timestamp)},
- {.iov_base = &display_period_ns, .iov_len = sizeof(display_period_ns)},
- {.iov_base = &right_eye_photon_offset_ns,
- .iov_len = sizeof(right_eye_photon_offset_ns)},
- };
- Transaction trans{*this};
- Status<int> status =
- trans.SendVector<int>(DVR_POSE_NOTIFY_VSYNC, data, nullptr);
- ALOGE_IF(!status, "Pose NotifyVsync() failed because: %s\n",
- status.GetErrorMessage().c_str());
- return ReturnStatusOrError(status);
- }
-
- int GetRingBufferFd(LocalHandle* fd) {
- int ret = GetRingBuffer(nullptr);
- if (ret < 0)
- return ret;
- *fd = pose_buffer_->GetBlobFd();
- return 0;
- }
-
private:
friend BASE;
@@ -252,14 +203,29 @@
PoseClient(const PoseClient&) = delete;
PoseClient& operator=(const PoseClient&) = delete;
- void GetPoseRingBufferInfo(DvrPoseRingBufferInfo* out_info) const {
- out_info->min_future_count = kPoseAsyncBufferMinFutureCount;
- out_info->total_count = kPoseAsyncBufferTotalCount;
- out_info->buffer = mapped_pose_buffer_->ring;
+ const DvrVsyncPoseBuffer* GetVsyncBuffer() {
+ if (mapped_vsync_pose_buffer_ == nullptr) {
+ if (vsync_pose_buffer_ == nullptr) {
+ // The constructor tries mapping it so we do not need TryMapping after.
+ vsync_pose_buffer_ = std::make_unique<CPUMappedBuffer>(
+ DvrGlobalBuffers::kVsyncPoseBuffer, CPUUsageMode::READ_OFTEN);
+ } else if (vsync_pose_buffer_->IsMapped() == false) {
+ vsync_pose_buffer_->TryMapping();
+ }
+
+ if (vsync_pose_buffer_->IsMapped()) {
+ mapped_vsync_pose_buffer_ =
+ static_cast<DvrVsyncPoseBuffer*>(vsync_pose_buffer_->Address());
+ }
+ }
+
+ return mapped_vsync_pose_buffer_;
}
- std::unique_ptr<BufferConsumer> pose_buffer_;
- const DvrPoseRingBuffer* mapped_pose_buffer_ = nullptr;
+ // The vsync pose buffer if already mapped.
+ std::unique_ptr<CPUMappedBuffer> vsync_pose_buffer_;
+
+ const DvrVsyncPoseBuffer* mapped_vsync_pose_buffer_ = nullptr;
struct ControllerClientState {
std::unique_ptr<BufferConsumer> pose_buffer;
@@ -273,66 +239,55 @@
using android::dvr::PoseClient;
-struct DvrPose {};
-
extern "C" {
-DvrPose* dvrPoseCreate() {
- PoseClient* client = PoseClient::Create().release();
- return reinterpret_cast<DvrPose*>(client);
+DvrPoseClient* dvrPoseClientCreate() {
+ auto* client = PoseClient::Create().release();
+ return reinterpret_cast<DvrPoseClient*>(client);
}
-void dvrPoseDestroy(DvrPose* client) { delete PoseClient::FromC(client); }
+void dvrPoseClientDestroy(DvrPoseClient* client) {
+ delete PoseClient::FromC(client);
+}
-int dvrPoseGet(DvrPose* client, uint32_t vsync_count, DvrPoseAsync* out_pose) {
+int dvrPoseClientGet(DvrPoseClient* client, uint32_t vsync_count,
+ DvrPoseAsync* out_pose) {
return PoseClient::FromC(client)->GetPose(vsync_count, out_pose);
}
-uint32_t dvrPoseGetVsyncCount(DvrPose* client) {
+uint32_t dvrPoseClientGetVsyncCount(DvrPoseClient* client) {
return PoseClient::FromC(client)->GetVsyncCount();
}
-int dvrPoseGetController(DvrPose* client, int32_t controller_id,
- uint32_t vsync_count, DvrPoseAsync* out_pose) {
+int dvrPoseClientGetController(DvrPoseClient* client, int32_t controller_id,
+ uint32_t vsync_count, DvrPoseAsync* out_pose) {
return PoseClient::FromC(client)->GetControllerPose(controller_id,
vsync_count, out_pose);
}
-int dvrPoseLogController(DvrPose* client, bool enable) {
+int dvrPoseClientLogController(DvrPoseClient* client, bool enable) {
return PoseClient::FromC(client)->LogController(enable);
}
-int dvrPosePoll(DvrPose* client, DvrPoseState* state) {
+int dvrPoseClientPoll(DvrPoseClient* client, DvrPose* state) {
return PoseClient::FromC(client)->Poll(state);
}
-int dvrPoseFreeze(DvrPose* client, const DvrPoseState* frozen_state) {
+int dvrPoseClientFreeze(DvrPoseClient* client, const DvrPose* frozen_state) {
return PoseClient::FromC(client)->Freeze(*frozen_state);
}
-int dvrPoseSetMode(DvrPose* client, DvrPoseMode mode) {
+int dvrPoseClientSetMode(DvrPoseClient* client, DvrPoseMode mode) {
return PoseClient::FromC(client)->SetMode(mode);
}
-int dvrPoseGetMode(DvrPose* client, DvrPoseMode* mode) {
+int dvrPoseClientGetMode(DvrPoseClient* client, DvrPoseMode* mode) {
return PoseClient::FromC(client)->GetMode(mode);
}
-int dvrPoseGetRingBuffer(DvrPose* client, DvrPoseRingBufferInfo* out_info) {
+int dvrPoseClientGetRingBuffer(DvrPoseClient* client,
+ DvrPoseRingBufferInfo* out_info) {
return PoseClient::FromC(client)->GetRingBuffer(out_info);
}
-int privateDvrPoseNotifyVsync(DvrPose* client, uint32_t vsync_count,
- int64_t display_timestamp,
- int64_t display_period_ns,
- int64_t right_eye_photon_offset_ns) {
- return PoseClient::FromC(client)->NotifyVsync(vsync_count, display_timestamp,
- display_period_ns,
- right_eye_photon_offset_ns);
-}
-
-int privateDvrPoseGetRingBufferFd(DvrPose* client, LocalHandle* fd) {
- return PoseClient::FromC(client)->GetRingBufferFd(fd);
-}
-
} // extern "C"
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 5cb201d..9201520 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -7,6 +7,7 @@
],
static_libs: [
+ "libbroadcastring",
"libhwcomposer-client",
"libdisplay",
"libbufferhubqueue",