Commit 16dacd0d authored by Kevin Qin's avatar Kevin Qin Committed by Commit Bot

Validate IPD plumbing gets exposed to JS

Test runtime actually updates IPD after session starts.
In this test, I checked if runtime passed the IPD to
js side. But we have to notice that fov and ipd is only updated in
the following conditions:
1. "when the canvas element for this session's output context is
resized."
2. when "ApplyPendingRenderState()" gets called

Bug: 996502
Change-Id: I26496d0997290fbd2330a2a22e7dd1d40c5226ec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1793946
Commit-Queue: Zheng Qin <zheqi@microsoft.com>
Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#696688}
parent ea3c4ed6
...@@ -16,6 +16,8 @@ namespace vr { ...@@ -16,6 +16,8 @@ namespace vr {
namespace { namespace {
const float kIPD = 0.2f;
struct Frame { struct Frame {
device_test::mojom::SubmittedFrameDataPtr submitted; device_test::mojom::SubmittedFrameDataPtr submitted;
device_test::mojom::PoseFrameDataPtr pose; device_test::mojom::PoseFrameDataPtr pose;
...@@ -56,7 +58,7 @@ class MyXRMock : public MockXRDeviceHookBase { ...@@ -56,7 +58,7 @@ class MyXRMock : public MockXRDeviceHookBase {
device_test::mojom::DeviceConfigPtr GetDeviceConfig() { device_test::mojom::DeviceConfigPtr GetDeviceConfig() {
auto config = device_test::mojom::DeviceConfig::New(); auto config = device_test::mojom::DeviceConfig::New();
config->interpupillary_distance = 0.2f; config->interpupillary_distance = kIPD;
config->projection_left = config->projection_left =
device_test::mojom::ProjectionRaw::New(0.1f, 0.2f, 0.3f, 0.4f); device_test::mojom::ProjectionRaw::New(0.1f, 0.2f, 0.3f, 0.4f);
config->projection_right = config->projection_right =
...@@ -170,6 +172,9 @@ WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestPresentationPoses) { ...@@ -170,6 +172,9 @@ WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestPresentationPoses) {
// Load the test page, and enter presentation. // Load the test page, and enter presentation.
t->LoadUrlAndAwaitInitialization( t->LoadUrlAndAwaitInitialization(
t->GetFileUrlForHtmlTestFile("test_webxr_poses")); t->GetFileUrlForHtmlTestFile("test_webxr_poses"));
ASSERT_TRUE(
t->RunJavaScriptAndExtractBoolOrFail("checkMagicWindowViewOffset()"))
<< "view under Magic Window should not have any offset from frame";
t->EnterSessionWithUserGestureOrFail(); t->EnterSessionWithUserGestureOrFail();
// Wait for JavaScript to submit at least one frame. // Wait for JavaScript to submit at least one frame.
...@@ -227,6 +232,10 @@ WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestPresentationPoses) { ...@@ -227,6 +232,10 @@ WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestPresentationPoses) {
ASSERT_TRUE(t->RunJavaScriptAndExtractBoolOrFail(base::StringPrintf( ASSERT_TRUE(t->RunJavaScriptAndExtractBoolOrFail(base::StringPrintf(
"checkFramePose(%d, %s)", frame_id, GetPoseAsString(frame).c_str()))) "checkFramePose(%d, %s)", frame_id, GetPoseAsString(frame).c_str())))
<< "JavaScript-side frame cache has incorrect pose"; << "JavaScript-side frame cache has incorrect pose";
ASSERT_TRUE(t->RunJavaScriptAndExtractBoolOrFail(
base::StringPrintf("checkFrameLeftEyeIPD(%d, %f)", frame_id, kIPD / 2)))
<< "JavaScript-side frame cache has incorrect eye position";
} }
// Tell JavaScript that it is done with the test. // Tell JavaScript that it is done with the test.
......
...@@ -18,6 +18,9 @@ test can query for whether each submitted frame used the correct pose. ...@@ -18,6 +18,9 @@ test can query for whether each submitted frame used the correct pose.
var frame_id = 0; var frame_id = 0;
var frame_data_array = {}; var frame_data_array = {};
var pose_array = {}; var pose_array = {};
var magic_window_frame_id = 0;
var magic_window_frame_position_array = {};
var magic_window_view_position_array = {};
// We exit presentation before checking stuff that needs the frame of // We exit presentation before checking stuff that needs the frame of
// reference, so we need to cache its value. // reference, so we need to cache its value.
var cached_frame_of_ref = null; var cached_frame_of_ref = null;
...@@ -33,6 +36,10 @@ test can query for whether each submitted frame used the correct pose. ...@@ -33,6 +36,10 @@ test can query for whether each submitted frame used the correct pose.
return true; return true;
} }
function PositionCompare(a, b) {
return FloatCompare(a.x, b.x) && FloatCompare(a.y, b.y) && FloatCompare(a.z, b.z);
}
function checkFrameOccurred(frame_id) { function checkFrameOccurred(frame_id) {
return frame_id in frame_data_array; return frame_id in frame_data_array;
} }
...@@ -58,6 +65,39 @@ test can query for whether each submitted frame used the correct pose. ...@@ -58,6 +65,39 @@ test can query for whether each submitted frame used the correct pose.
return MatrixCompare(pose.transform.matrix, expected); return MatrixCompare(pose.transform.matrix, expected);
} }
function checkFrameLeftEyeIPD(frame_id, expected) {
let left_eye = null;
if (pose_array[frame_id].views[0].eye == "left") {
left_eye = pose_array[frame_id].views[0];
} else {
left_eye = pose_array[frame_id].views[1];
}
let position = left_eye.transform.position;
console.log(position.x)
return FloatCompare(position.x, expected);
}
function checkMagicWindowViewOffset() {
for (i = 1; i <= magic_window_frame_id; i++) {
let magic_window_frame_position = magic_window_frame_position_array[i];
let magic_window_view_position = magic_window_view_position_array[i];
if (!PositionCompare(magic_window_frame_position, magic_window_view_position)) {
return false;
}
}
return true;
}
onMagicWindowXRFrameCallback = function(session, frame) {
magic_window_frame_id++;
cached_frame_of_ref = sessionInfos[sessionTypes.MAGIC_WINDOW].currentRefSpace;
let pose = frame.getViewerPose(cached_frame_of_ref);
magic_window_frame_position_array[magic_window_frame_id] = pose.transform.position;
let view = pose.views[0];
magic_window_view_position_array[magic_window_frame_id] = view.transform.position;
}
onImmersiveXRFrameCallback = function(session, frame, gl) { onImmersiveXRFrameCallback = function(session, frame, gl) {
// Encode an index into the clear color. // Encode an index into the clear color.
frame_id++; frame_id++;
......
...@@ -439,7 +439,8 @@ HmdMatrix34_t TestVRSystem::GetEyeToHeadTransform(EVREye eye) { ...@@ -439,7 +439,8 @@ HmdMatrix34_t TestVRSystem::GetEyeToHeadTransform(EVREye eye) {
ret.m[0][0] = 1; ret.m[0][0] = 1;
ret.m[1][1] = 1; ret.m[1][1] = 1;
ret.m[2][2] = 1; ret.m[2][2] = 1;
ret.m[0][3] = (eye == Eye_Left) ? 0.1f : -0.1f; float ipd = g_test_helper.GetInterpupillaryDistance();
ret.m[0][3] = ((eye == Eye_Left) ? 1 : -1) * ipd / 2;
return ret; return ret;
} }
......
...@@ -582,6 +582,11 @@ XrResult xrLocateViews(XrSession session, ...@@ -582,6 +582,11 @@ XrResult xrLocateViews(XrSession session,
XR_ERROR_VALIDATION_FAILURE, XR_ERROR_VALIDATION_FAILURE,
"xrLocateViews view_locate_info type invalid"); "xrLocateViews view_locate_info type invalid");
RETURN_IF_XR_FAILED(g_test_helper.ValidateSpace(view_locate_info->space)); RETURN_IF_XR_FAILED(g_test_helper.ValidateSpace(view_locate_info->space));
if (view_capacity_input != 0) {
RETURN_IF_FALSE(g_test_helper.UpdateViewFOV(views, view_capacity_input),
XR_ERROR_VALIDATION_FAILURE,
"xrLocateViews UpdateViewFOV failed");
}
return XR_SUCCESS; return XR_SUCCESS;
} }
......
...@@ -458,6 +458,18 @@ bool OpenXrTestHelper::UpdateData() { ...@@ -458,6 +458,18 @@ bool OpenXrTestHelper::UpdateData() {
return false; return false;
} }
bool OpenXrTestHelper::UpdateViewFOV(XrView views[], uint32_t size) {
RETURN_IF(size != 2, XR_ERROR_VALIDATION_FAILURE,
"UpdateViewFOV currently only supports 2 viewports config");
base::AutoLock auto_lock(lock_);
if (test_hook_) {
auto config = test_hook_->WaitGetDeviceConfig();
views[0].pose.position.x = config.interpupillary_distance / 2;
views[1].pose.position.x = -config.interpupillary_distance / 2;
}
return true;
}
XrResult OpenXrTestHelper::ValidateAction(XrAction action) const { XrResult OpenXrTestHelper::ValidateAction(XrAction action) const {
RETURN_IF(actions_.count(action) != 1, XR_ERROR_HANDLE_INVALID, RETURN_IF(actions_.count(action) != 1, XR_ERROR_HANDLE_INVALID,
"ValidateAction: Invalid Action"); "ValidateAction: Invalid Action");
......
...@@ -64,6 +64,7 @@ class OpenXrTestHelper : public device::ServiceTestHook { ...@@ -64,6 +64,7 @@ class OpenXrTestHelper : public device::ServiceTestHook {
void GetPose(XrPosef* pose); void GetPose(XrPosef* pose);
std::string PathToString(XrPath path) const; std::string PathToString(XrPath path) const;
bool UpdateData(); bool UpdateData();
bool UpdateViewFOV(XrView views[], uint32_t size);
uint32_t NextSwapchainImageIndex(); uint32_t NextSwapchainImageIndex();
XrTime NextPredictedDisplayTime(); XrTime NextPredictedDisplayTime();
......
...@@ -135,7 +135,13 @@ bool MockWMRCameraPose::TryGetViewTransform( ...@@ -135,7 +135,13 @@ bool MockWMRCameraPose::TryGetViewTransform(
float col_major_transform[16]; float col_major_transform[16];
origin_to_device.matrix().asColMajorf(col_major_transform); origin_to_device.matrix().asColMajorf(col_major_transform);
// index of matrix[3][0] in 1d array
int index = 3 * 4;
float original_x = col_major_transform[index];
float ipd = hook.GetHook()->WaitGetDeviceConfig().interpupillary_distance;
col_major_transform[index] = original_x - ipd / 2;
CopyRowMajorFloatArrayToWindowsMatrix(col_major_transform, transform->Left); CopyRowMajorFloatArrayToWindowsMatrix(col_major_transform, transform->Left);
col_major_transform[index] = original_x + ipd / 2;
CopyRowMajorFloatArrayToWindowsMatrix(col_major_transform, transform->Right); CopyRowMajorFloatArrayToWindowsMatrix(col_major_transform, transform->Right);
return true; return true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment