diff --git a/testing/web-platform/tests/resources/chromium/webxr-test.js b/testing/web-platform/tests/resources/chromium/webxr-test.js index 31bf916caf80..e584ea37cb37 100644 --- a/testing/web-platform/tests/resources/chromium/webxr-test.js +++ b/testing/web-platform/tests/resources/chromium/webxr-test.js @@ -12,8 +12,9 @@ class ChromeXRTest { return Promise.resolve(this.mockVRService_.addRuntime(init_params)); } - simulateDeviceDisconnection(device) { - this.mockVRService_.removeRuntime(device); + disconnectAllDevices() { + this.mockVRService_.removeAllRuntimes(device); + return Promise.resolve(); } simulateUserActivation(callback) { @@ -60,11 +61,11 @@ class MockVRService { return runtime; } - removeRuntime(runtime) { - // We have no way of distinguishing between devices, so just clear the - // entire list for now. - // TODO(http://crbug.com/873409) We also have no way right now to disconnect - // devices. + removeAllRuntimes() { + if (this.client_) { + this.client_.onDeviceChanged(); + } + this.runtimes_ = []; } @@ -151,6 +152,8 @@ class MockRuntime { this.framesOfReference = {}; + // Initialize DisplayInfo first to set the defaults, then override with + // anything from the deviceInit if (fakeDeviceInit.supportsImmersive) { this.displayInfo_ = this.getImmersiveDisplayInfo(); } else { @@ -160,16 +163,16 @@ class MockRuntime { if (fakeDeviceInit.supportsEnvironmentIntegration) { this.displayInfo_.capabilities.canProvideEnvironmentIntegration = true; } - } - // Test methods. - setXRPresentationFrameData(poseMatrix, views) { - if (poseMatrix == null) { - this.pose_ = null; - } else { - this.setPoseFromMatrix(poseMatrix); + if (fakeDeviceInit.viewerOrigin != null) { + this.setViewerOrigin(fakeDeviceInit.viewerOrigin); } + this.setViews(fakeDeviceInit.views); + } + + // Test API methods. + setViews(views) { if (views) { let changed = false; for (let i = 0; i < views.length; i++) { @@ -182,17 +185,18 @@ class MockRuntime { } } - if (changed) { + if (changed && this.sessionClient_.ptr.isBound()) { this.sessionClient_.onChanged(this.displayInfo_); } } } - - setPoseFromMatrix(poseMatrix) { + setViewerOrigin(origin, emulatedPosition = false) { + let p = origin.position; + let q = origin.orientation; this.pose_ = { - orientation: null, - position: null, + orientation: { x: q[0], y: q[1], z: q[2], w: q[3] }, + position: { x: p[0], y: p[1], z: p[2] }, angularVelocity: null, linearVelocity: null, angularAcceleration: null, @@ -200,37 +204,13 @@ class MockRuntime { inputState: null, poseIndex: 0 }; - - let pose = this.poseFromMatrix(poseMatrix); - for (let field in pose) { - if (this.pose_.hasOwnProperty(field)) { - this.pose_[field] = pose[field]; - } - } } - poseFromMatrix(m) { - let m00 = m[0]; - let m11 = m[5]; - let m22 = m[10]; - - // The max( 0, ... ) is just a safeguard against rounding error. - let orientation = new gfx.mojom.Quaternion(); - orientation.w = Math.sqrt(Math.max(0, 1 + m00 + m11 + m22)) / 2; - orientation.x = Math.sqrt(Math.max(0, 1 + m00 - m11 - m22)) / 2; - orientation.y = Math.sqrt(Math.max(0, 1 - m00 + m11 - m22)) / 2; - orientation.z = Math.sqrt(Math.max(0, 1 - m00 - m11 + m22)) / 2; - - let position = new gfx.mojom.Point3F(); - position.x = m[12]; - position.y = m[13]; - position.z = m[14]; - - return { - orientation, position - } + clearViewerOrigin() { + this.pose_ = null; } + // Helper methods getNonImmersiveDisplayInfo() { let displayInfo = this.getImmersiveDisplayInfo(); @@ -296,6 +276,8 @@ class MockRuntime { let upTan = (1 + m[9]) / m[5]; let downTan = (1 - m[9]) / m[5]; + let offset = fakeXRViewInit.viewOffset.position; + return { fieldOfView: { upDegrees: toDegrees(upTan), @@ -303,9 +285,9 @@ class MockRuntime { leftDegrees: toDegrees(leftTan), rightDegrees: toDegrees(rightTan) }, - offset: { x: 0, y: 0, z: 0 }, - renderWidth: 20, - renderHeight: 20 + offset: { x: offset[0], y: offset[1], z: offset[2] }, + renderWidth: fakeXRViewInit.resolution.width, + renderHeight: fakeXRViewInit.resolution.height }; } @@ -405,6 +387,7 @@ class MockRuntime { }; } +// Mojo helper classes class MockXRPresentationProvider { constructor() { this.binding_ = new mojo.Binding(device.mojom.XRPresentationProvider, this); @@ -448,4 +431,21 @@ class MockXRPresentationProvider { } } +// This is a temporary workaround for the fact that spinning up webxr before +// the mojo interceptors are created will cause the interceptors to not get +// registered, so we have to create this before we query xr; let XRTest = new ChromeXRTest(); + +// This test API is also used to run Chrome's internal legacy VR tests; however, +// those fail if navigator.xr has been used. Those tests will set a bool telling +// us not to try to check navigator.xr +if ((typeof legacy_vr_test === 'undefined') || !legacy_vr_test) { + // Some tests may run in the http context where navigator.xr isn't exposed + // This should just be to test that it isn't exposed, but don't try to set up + // the test framework in this case. + if (navigator.xr) { + navigator.xr.test = XRTest; + } +} else { + navigator.vr = { test: XRTest }; +} diff --git a/testing/web-platform/tests/webxr/resources/test-constants.js b/testing/web-platform/tests/webxr/resources/test-constants.js deleted file mode 100644 index aab0417aed0b..000000000000 --- a/testing/web-platform/tests/webxr/resources/test-constants.js +++ /dev/null @@ -1,32 +0,0 @@ -// assert_equals can fail when comparing floats due to precision errors, so -// use assert_approx_equals with this constant instead -const FLOAT_EPSILON = 0.001; - -// Identity matrix -const IDENTITY_MATRIX = [1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1]; - -// A valid pose matrix for when we don't care about specific values -const VALID_POSE_MATRIX = [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1]; - -const VALID_PROJECTION_MATRIX = - [1, 0, 0, 0, 0, 1, 0, 0, 3, 2, -1, -1, 0, 0, -0.2, 0]; - -const VALID_VIEW_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 3, 2, 1]; - -// A valid VRPose for when we want the HMD to report being at the origin -const ORIGIN_POSE = IDENTITY_MATRIX; - -// A valid input grip matrix for when we don't care about specific values -const VALID_GRIP = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 3, 2, 1]; - -// A valid input pointer offset for when we don't care about specific values -const VALID_POINTER_OFFSET = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1]; - -const VALID_GRIP_WITH_POINTER_OFFSET = - [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 3, 3, 1]; - -const VALID_STAGE_TRANSFORM = - [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1.0, 1.65, -1.0, 1]; diff --git a/testing/web-platform/tests/webxr/resources/webxr_test_constants.js b/testing/web-platform/tests/webxr/resources/webxr_test_constants.js index c38c012ba846..a846f1da75fe 100644 --- a/testing/web-platform/tests/webxr/resources/webxr_test_constants.js +++ b/testing/web-platform/tests/webxr/resources/webxr_test_constants.js @@ -8,17 +8,26 @@ const IDENTITY_MATRIX = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; -// A valid pose matrix for when we don't care about specific values -const VALID_POSE_MATRIX = [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1]; +const IDENTITY_TRANSFORM = { + position: [0, 0, 0], + orientation: [0, 0, 0, 1], +}; + +// A valid pose matrix/transform for when we don't care about specific values +// Note that these two should be identical, just different representations +const VALID_POSE_MATRIX = [0, 1, 0, 0, + 0, 0, 1, 0, + 1, 0, 0, 0, + 1, 1, 1, 1]; + +const VALID_POSE_TRANSFORM = { + position: [1, 1, 1], + orientation: [0.5, 0.5, 0.5, 0.5] +}; const VALID_PROJECTION_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 3, 2, -1, -1, 0, 0, -0.2, 0]; -const VALID_VIEW_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 3, 2, 1]; - -// A valid VRPose for when we want the HMD to report being at the origin -const ORIGIN_POSE = IDENTITY_MATRIX; - // A valid input grip matrix for when we don't care about specific values const VALID_GRIP = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 3, 2, 1]; @@ -39,3 +48,51 @@ const VALID_BOUNDS = [ { x: -3.5, y: 0, z: 0.0 }, { x: -3.0, y: 0, z: -2.0 } ]; + +const VALID_RESOLUTION = { + width: 20, + height: 20 +}; + +const LEFT_OFFSET = { + position: [-0.1, 0, 0], + orientation: [0, 0, 0, 1] +}; + +const RIGHT_OFFSET = { + position: [0.1, 0, 0], + orientation: [0, 0, 0, 1] +}; + +const VALID_VIEWS = [{ + eye:"left", + projectionMatrix: VALID_PROJECTION_MATRIX, + viewOffset: LEFT_OFFSET, + resolution: VALID_RESOLUTION + }, { + eye:"right", + projectionMatrix: VALID_PROJECTION_MATRIX, + viewOffset: RIGHT_OFFSET, + resolution: VALID_RESOLUTION + }, +]; + +const NON_IMMERSIVE_VIEWS = [{ + eye: "none", + projectionMatrix: VALID_PROJECTION_MATRIX, + viewOffset: IDENTITY_TRANSFORM, + resolution: VALID_RESOLUTION, + } +]; + +const TRACKED_IMMERSIVE_DEVICE = { + supportsImmersive: true, + views: VALID_VIEWS, + viewerOrigin: IDENTITY_TRANSFORM +}; + +const VALID_NON_IMMERSIVE_DEVICE = { + supportsImmersive: false, + views: NON_IMMERSIVE_VIEWS, + viewerOrigin: IDENTITY_TRANSFORM +}; diff --git a/testing/web-platform/tests/webxr/resources/webxr_util.js b/testing/web-platform/tests/webxr/resources/webxr_util.js index 860d363f2c96..54a91c85c86a 100644 --- a/testing/web-platform/tests/webxr/resources/webxr_util.js +++ b/testing/web-platform/tests/webxr/resources/webxr_util.js @@ -39,15 +39,15 @@ function xr_session_promise_test( xr_promise_test( name, - (t) => - XRTest.simulateDeviceConnection(fakeDeviceInit) + (t) =>{ + return navigator.xr.test.simulateDeviceConnection(fakeDeviceInit) .then((controller) => { testDeviceController = controller; return gl.makeXRCompatible(); }) .then(() => new Promise((resolve, reject) => { // Perform the session request in a user gesture. - XRTest.simulateUserActivation(() => { + navigator.xr.test.simulateUserActivation(() => { navigator.xr.requestSession(sessionMode) .then((session) => { testSession = session; @@ -75,8 +75,9 @@ function xr_session_promise_test( .then(() => { // Cleanup system state. testSession.end().catch(() => {}); - XRTest.simulateDeviceDisconnection(); - }), + return navigator.xr.test.disconnectAllDevices(); + }) + }, properties); } @@ -138,4 +139,4 @@ let loadChromiumResources = Promise.resolve().then(() => { }); return chain; -}); \ No newline at end of file +}); diff --git a/testing/web-platform/tests/webxr/webGLCanvasContext_create_xrcompatible.https.html b/testing/web-platform/tests/webxr/webGLCanvasContext_create_xrcompatible.https.html index 8b2f196fa76e..b83b9601aed1 100644 --- a/testing/web-platform/tests/webxr/webGLCanvasContext_create_xrcompatible.https.html +++ b/testing/web-platform/tests/webxr/webGLCanvasContext_create_xrcompatible.https.html @@ -3,11 +3,12 @@ + + + - \ No newline at end of file + diff --git a/testing/web-platform/tests/webxr/xrDevice_requestSession_immersive_no_gesture.https.html b/testing/web-platform/tests/webxr/xrDevice_requestSession_immersive_no_gesture.https.html index eb5a4fda0bdf..10e15b63244d 100644 --- a/testing/web-platform/tests/webxr/xrDevice_requestSession_immersive_no_gesture.https.html +++ b/testing/web-platform/tests/webxr/xrDevice_requestSession_immersive_no_gesture.https.html @@ -3,11 +3,12 @@ + + + + + diff --git a/testing/web-platform/tests/webxr/xrDevice_supportsSession_immersive_unsupported.https.html b/testing/web-platform/tests/webxr/xrDevice_supportsSession_immersive_unsupported.https.html index 0fb44a895d1f..1d63a2b1c3a2 100644 --- a/testing/web-platform/tests/webxr/xrDevice_supportsSession_immersive_unsupported.https.html +++ b/testing/web-platform/tests/webxr/xrDevice_supportsSession_immersive_unsupported.https.html @@ -3,11 +3,12 @@ + + - + @@ -11,20 +11,9 @@ let immersiveTestName = "XRFrame.getPose works for immersive sessions"; let nonImmersiveTestName = "XRFrame.getPose works for non-immersive sessions"; -let fakeDeviceInitParams = { supportsImmersive:true }; +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; let testFunction = function(session, fakeDeviceController, t) { - // Need to have a valid pose or input events don't process. - fakeDeviceController.setXRPresentationFrameData(VALID_POSE_MATRIX, [{ - eye:"left", - projectionMatrix: VALID_PROJECTION_MATRIX, - viewMatrix: VALID_VIEW_MATRIX - }, { - eye:"right", - projectionMatrix: VALID_PROJECTION_MATRIX, - viewMatrix: VALID_VIEW_MATRIX - }]); - return Promise.all([ session.requestReferenceSpace('local'), session.requestReferenceSpace('local') diff --git a/testing/web-platform/tests/webxr/xrFrame_lifetime.https.html b/testing/web-platform/tests/webxr/xrFrame_lifetime.https.html index 27ef02de3374..c7af792c7bb4 100644 --- a/testing/web-platform/tests/webxr/xrFrame_lifetime.https.html +++ b/testing/web-platform/tests/webxr/xrFrame_lifetime.https.html @@ -3,6 +3,7 @@ + - \ No newline at end of file + diff --git a/testing/web-platform/tests/webxr/xrRay_constructor.https.html b/testing/web-platform/tests/webxr/xrRay_constructor.https.html index ebf88845b0cd..b955db4509c2 100644 --- a/testing/web-platform/tests/webxr/xrRay_constructor.https.html +++ b/testing/web-platform/tests/webxr/xrRay_constructor.https.html @@ -3,7 +3,6 @@ - - - - - + + + - \ No newline at end of file + diff --git a/testing/web-platform/tests/webxr/xrSession_prevent_multiple_exclusive.https.html b/testing/web-platform/tests/webxr/xrSession_prevent_multiple_exclusive.https.html index e61bd392718a..cd1407037849 100644 --- a/testing/web-platform/tests/webxr/xrSession_prevent_multiple_exclusive.https.html +++ b/testing/web-platform/tests/webxr/xrSession_prevent_multiple_exclusive.https.html @@ -3,18 +3,19 @@ + + - \ No newline at end of file + diff --git a/testing/web-platform/tests/webxr/xrSession_requestAnimationFrame_data_valid.https.html b/testing/web-platform/tests/webxr/xrSession_requestAnimationFrame_data_valid.https.html index c5108e4eccf9..760ff3dd657f 100644 --- a/testing/web-platform/tests/webxr/xrSession_requestAnimationFrame_data_valid.https.html +++ b/testing/web-platform/tests/webxr/xrSession_requestAnimationFrame_data_valid.https.html @@ -3,31 +3,13 @@ + + + + - \ No newline at end of file + diff --git a/testing/web-platform/tests/webxr/xrSession_viewer_referenceSpace.https.html b/testing/web-platform/tests/webxr/xrSession_viewer_referenceSpace.https.html index 85e5e87f8266..fd6082bc3468 100644 --- a/testing/web-platform/tests/webxr/xrSession_viewer_referenceSpace.https.html +++ b/testing/web-platform/tests/webxr/xrSession_viewer_referenceSpace.https.html @@ -3,6 +3,7 @@ + - + @@ -11,20 +11,9 @@ let immersiveTestName = "XRView.eye is correct for immersive sessions"; let nonImmersiveTestName = "XRView.eye is correct for non-immersive sessions"; -let fakeDeviceInitParams = { supportsImmersive:true }; +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; let testFunction = function(session, fakeDeviceController, t) { - // Need to have a valid pose or input events don't process. - fakeDeviceController.setXRPresentationFrameData(VALID_POSE_MATRIX, [{ - eye:"left", - projectionMatrix: VALID_PROJECTION_MATRIX, - viewMatrix: VALID_VIEW_MATRIX - }, { - eye:"right", - projectionMatrix: VALID_PROJECTION_MATRIX, - viewMatrix: VALID_VIEW_MATRIX - }]); - return session.requestReferenceSpace('viewer') .then((space) => new Promise((resolve) => { function onFrame(time, xrFrame) { diff --git a/testing/web-platform/tests/webxr/xrWebGLLayer_viewports.https.html b/testing/web-platform/tests/webxr/xrWebGLLayer_viewports.https.html index f789e4733548..247e3b779d61 100644 --- a/testing/web-platform/tests/webxr/xrWebGLLayer_viewports.https.html +++ b/testing/web-platform/tests/webxr/xrWebGLLayer_viewports.https.html @@ -1,7 +1,7 @@ - + @@ -11,20 +11,9 @@ let immersiveTestName = "XRWebGLLayer reports a valid viewports for immersive sessions"; let inlineTestName = "XRWebGLLayer reports a valid viewports for inline sessions"; -let fakeDeviceInitParams = { supportsImmersive:true }; +let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; let testFunction = function(session, fakeDeviceController, t) { - // Need to have a valid pose. - fakeDeviceController.setXRPresentationFrameData(VALID_POSE_MATRIX, [{ - eye:"left", - projectionMatrix: VALID_PROJECTION_MATRIX, - viewMatrix: VALID_VIEW_MATRIX - }, { - eye:"right", - projectionMatrix: VALID_PROJECTION_MATRIX, - viewMatrix: VALID_VIEW_MATRIX - }]); - return session.requestReferenceSpace('viewer') .then((space) => new Promise((resolve) => { function onFrame(time, xrFrame) {