Adopt the use of shared buffers.
Bug: 37001948
Test: Make system image
Change-Id: I032574f250e0f0fe7768af649730406e24d853db
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);