1. Introduction
In order to allow Web Platform Tests for WebXR there are some basic functions which are common across all tests, such as adding a fake test device and specifying poses. Below is an API which attempts to capture the necessary functions, based off what was defined in the spec. Different browser vendors can implement this API in whatever way is most compatible with their browser. For example, some browsers may back the interface with a WebDriver API while others may use HTTP or IPC mechanisms to communicate with an out of process fake backend.
These initialization object and control interfaces do not represent a complete set of WebXR functionality, and are expected to be expanded on as the WebXR spec grows.
2. Conformance
Interfaces and functionality exposed by this specification SHOULD NOT be exposed to typical browsing experiences, and instead SHOULD only be used when running Web Platform Tests.
3. Simulated devices
3.1. Simulated XR Device
This API gives tests the ability to spin up a simulated XR device which is an XR device which from the point of view of the WebXR API behaves like a normal XR device. These simulated XR devices can be controlled by the associatedFakeXRDevice object.
Every simulated XR device may have an native bounds geometry which is an array of DOMPointReadOnlys, used to initialize the native bounds geometry of any XRBoundedReferenceSpaces created for the device. If null, the device is treated as if it is not currently tracking a bounded reference space.
Every simulated XR device may have a floor origin which is an XRRigidTransform used to note the position of the physical floor. If null, the device is treated as if it is unable to identify the physical floor.
Every simulated XR device may have an viewer origin which is an XRRigidTransform used to set the position and orientation of the viewer. If null, the device is treated as if it has lost tracking.
Every simulated XR device has an emulated position boolean which is a boolean used to set the emulatedPosition of any XRPoses produced involving the viewer. This is initially false.
Every simulated XR device has an visibility state which is an XRVisibilityState used to set the visibilityState of any XRSessions associated with the simulated XR device . This is initially "visible". When it is changed, the associated changes must be reflected on the XRSession, including triggering onvisibilitychange events if necessary.
Every simulated XR device has a list of primary views which is a list of views that must be rendered to for an immersive experience. There must be at least one primary view.
Every simulated XR device may have a list of secondary views which is a list of views that may or may not be rendered to. There may be any number of secondary views.
Every view for a simulated XR device has an associated device resolution, which is an instance of FakeXRDeviceResolution. This resolution must be used when constructing XRViewport values for the view, based on the canvas size.
Every view for a simulated XR device has an associated id, which is the index of the view in the views list, and thus matches the index.
Every view for a simulated XR device may have an associated field of view, which is an instance of FakeXRFieldOfViewInit used to calculate projection matrices using depth values. If the field of view is set, projection matrix values are calculated using the field of view and depthNear and depthFar values.
Every view for a simulated XR device may have an associated visibility mask which is an instance of FakeXRVisibilityMask used to describe the visible region of the view. If it is missing, the entire view is visible. Changes to this value should result in firing a XRVisibilityMaskChangeEvent no later than the next animation frame.
Every simulated XR device has a supported depth types which is a list of XRDepthType values, initially empty. If this list is empty, it implies all XRDepthType values are supported.
Every simulated XR device has a supported depth formats which is a list of XRDepthFormat values, initially empty. If this list is empty, it implies all XRDepthFormat values are supported.
Every simulated XR device has a supported depth usages which is a list of XRDepthUsage values, initially empty. If this list is empty, it implies all XRDepthUsage values are supported.
3.2. Simulated Input Device
This API gives tests the ability to spin up a simulated XR input source which is an XR input source which from the point of view of the WebXR API behaves like a normal XR input source. These simulated XR input sources can be controlled by the associated FakeXRInputController object.
Every simulated XR input source has a handedness which is an XRHandedness value that MUST be returned for the corresponding XR input source’s handedness attribute.
Every simulated XR input source has a targetRayMode which is an XRTargetRayMode value that MUST be returned for the corresponding XR input source’s targetRayMode attribute.
Every simulated XR input source has a pointerOrigin which is an XRRigidTransform used to note the origin of the targetRaySpace.
A simulated XR input source may have a gripOrigin which is an XRRigidTransform used to note the origin of the gripSpace. If this is null the simulated XR input source is not tracked.
Every simulated XR input source has a profiles array which is an array of DOMStrings which MUST be returned for the corresponding XR input source’s profiles attribute.
Every simulated XR input source has a buttonState array which is an array of FakeXRButtonStateInits. If a "grip" button is specified, it SHOULD drive the primary squeeze action. If a UA implements the WebXR Gamepads Module buttonState SHOULD be used to set the state for the corresponding XR input source’s gamepad object, which SHOULD be of type "xr-standard" if enough buttons are specified to support it.
Every simulated XR input source has a connectionState which is a boolean that is initially true and indicates whether the associated XR input source should appear in inputSources. When it is changed the associated changes must be reflected on the XRSession, including triggering the inputsourceschange event if necessary by the next animation frame.
Every simulated XR input source has a primaryActionStarted which is a boolean, initially set to false, that indicates whether or not the primary action of the XR input source has been started.
4. Initialization
4.1. navigator.xr.test
partial interface XRSystem { [SameObject ]readonly attribute XRTest test ; };
The test attribute’s getter MUST return the XRTest object that is associated with it. This object MAY be lazily created.
4.2. XRTest
The XRTest object is the entry point for all testing.
interface {XRTest Promise <FakeXRDevice >simulateDeviceConnection (FakeXRDeviceInit );init undefined simulateUserActivation (Function );f Promise <undefined >disconnectAllDevices (); };
simulateDeviceConnection(init) method creates a new simulated XR device.
When this method is invoked, the user agent MUST run the following steps:
-
Let promise be a new Promise.
-
Run the following steps in parallel:
-
Let device be a new simulated XR device.
-
Run the following steps to set device’s views.
-
Let l be the result of running parse a list of views on
views. -
If running parse a list of views threw an error, reject promise with this error and abort these steps.
-
Set device’s list of primary views to l.
-
If init’s
secondaryViewsis set:-
Let sl be the result of running parse a list of views on
secondaryViews. -
If running parse a list of views threw an error, reject promise with this error and abort these steps.
-
Set device’s list of secondary views to sl.
-
-
If init’s
boundsCoordinatesis set, perform the following steps:-
If init’s
boundsCoordinateshas less than 3 elements, reject promise withTypeErrorand abort these steps. -
Set device’s native bounds geometry to init’s
boundsCoordinates.
-
-
If init’s
floorOriginis set, set device’s floor origin to init’sfloorOrigin. -
If init’s
viewerOriginis set, set device’s viewer origin to init’sviewerOrigin. -
Let supportedModes be an empty list of
XRSessionModes. -
Modify supportedModes as follows:
- If init’s
supportedModesis present: -
-
Append the contents of init’s
supportedModesto supportedModes. -
If supportedModes is empty, append
"inline"to it.
-
- Else
-
-
Append
"inline"to supportedModes. -
If init’s
supportsImmersiveistrue, append"immersive-vr"to supportedModes.
-
- If init’s
-
If init’s
supportedFeaturesis set, for each mode in supportedModes: -
Associate init’s
supportedFeaturesto mode -
If init’s
depthSupportis present:-
Let depthConfig be init’s
depthSupport. -
If depthConfig’s
depthTypesis present and its size is greater than 0, set device’s supported depth types to a copy of depthConfig’sdepthTypes. -
If depthConfig’s
depthFormatsis present and its size is greater than 0, set device’s supported depth formats to a copy of depthConfig’sdepthFormats. -
If depthConfig’s
depthUsagesis present and its size is greater than 0, set device’s supported depth usages to a copy of depthConfig’sdepthUsages.
-
-
NOTE: each device stores a list of features it is capable of supporting per XRSessionMode. Most tests only test one mode anyway so there isn’t much to be gained by splitting features per mode in FakeXRDeviceInit. Users wishing different modes supporting different features should create multiple devices instead.
-
Set device’s list of supported modes to supportedModes.
-
Register device based on the following:
-
If supportedModes contains
"immersive-vr"or"immersive-ar", append device to thexr’s list of immersive XR devices. -
If supportedModes contains
"inline", set the inline XR device to device.
-
-
Let d be a new
FakeXRDeviceobject with device as device. -
Resolve promise with d.
-
Return promise.
When simulateUserActivation(f) is called, invoke f as if it had transient activation.
When disconnectAllDevices() is called, remove all simulated XR devices from the xr’s list of immersive XR devices as if they were disconnected. If the inline XR device is a simulated XR device, reset it to the default inline XR device.
4.3. FakeXRDeviceInit
dictionary {FakeXRDeviceInit required boolean ;supportsImmersive sequence <XRSessionMode >;supportedModes required sequence <FakeXRViewInit >;views sequence <FakeXRViewInit >;secondaryViews sequence <any >;supportedFeatures sequence <FakeXRBoundsPoint >;boundsCoordinates FakeXRRigidTransformInit ;floorOrigin FakeXRRigidTransformInit ; // Hit test extensions:viewerOrigin FakeXRWorldInit ; // Depth sensing extensions:world FakeXRDepthSensingDataInit ;depthSensingData FakeXRDepthConfigurationSupport ; };depthSupport dictionary {FakeXRViewInit required XREye ;eye required sequence <float >;projectionMatrix required FakeXRDeviceResolution ;resolution required FakeXRRigidTransformInit ;viewOffset FakeXRFieldOfViewInit ;fieldOfView FakeXRVisibilityMask ; // Raw camera access extensions:visibilityMask FakeXRCameraImage ; };cameraImageInit dictionary {FakeXRFieldOfViewInit required float ;upDegrees required float ;downDegrees required float ;leftDegrees required float ; };rightDegrees dictionary {FakeXRDeviceResolution required long ;width required long ; };height dictionary {FakeXRBoundsPoint double ;x double ; };z dictionary {FakeXRRigidTransformInit required sequence <float >;position required sequence <float >; };orientation dictionary {FakeXRVisibilityMask required sequence <float >;vertices required sequence <uint32 >; };indices
The supportsImmersive is deprecated in favor of supportedModes and will be removed in future revisions of the specification.
FakeXRRigidTransformInit init, perform the following steps:
-
Let p be init’s
position. -
If p does not have three elements, throw a
TypeError. -
Let o be init’s
orientation. -
If o does not have four elements, throw a
TypeError. -
Let position be a
DOMPointInitwithx,yandzequal to the three elements of p in order, andwequal to1. -
Let orientation be a
DOMPointInitwithx,y,z, andwequal to the four elements of o in order. -
Construct an XRRigidTransformtransform withpositionposition andorientationorientation. -
Return transform.
FakeXRViewInit init, and `uint32_t` id perform the following steps:
-
Let view be a new view.
-
Set view’s id to id.
-
If init’s
projectionMatrixdoes not have 16 elements, throw aTypeError. -
Set view’s projection matrix to init’s
projectionMatrix. -
Set view’s view offset to the result of running parse a rigid transform init’s
viewOffset. -
Set view’s device resolution to init’s
resolution. -
If init’s
fieldOfViewis set, perform the following steps:-
Set view’s field of view to init’s
fieldOfView. -
Set view’s projection matrix to the projection matrix corresponding to this field of view, and depth values equal to
depthNearanddepthFarof anyXRSessionassociated with the device. If there currently is none, use the default values ofnear=0.1, far=1000.0.
-
-
If init’s
visibilityMaskis set, set view’s visibility mask to init’svisibilityMask -
Return view.
4.4. FakeXRRigidTransformInit
The WebXR API never exposes native origins directly, instead exposing transforms between them, so we need to specify a base reference space forFakeXRRigidTransformInits so that we can have consistent numerical values across implementations. When used as an origin, FakeXRRigidTransformInits are in the base reference space where the viewer’s native origin is identity at initialization, unless otherwise specified. In this space, the "local" reference space has a native origin of identity. This is an arbitrary choice: changing this reference space doesn’t affect the data returned by the WebXR API, but we must make such a choice so that the tests produce the same results across different UAs. When used as an origin it is logically a transform from the origin’s space to the underlying base reference space described above.
5. Mocking
5.1. FakeXRDevice
interface :FakeXRDevice EventTarget {undefined setViews (sequence <FakeXRViewInit >,views optional sequence <FakeXRViewInit >);secondaryViews Promise <undefined >disconnect ();undefined setViewerOrigin (FakeXRRigidTransformInit ,origin optional boolean =emulatedPosition false );undefined clearViewerOrigin ();undefined setFloorOrigin (FakeXRRigidTransformInit );origin undefined clearFloorOrigin ();undefined setBoundsGeometry (sequence <FakeXRBoundsPoint >);boundsCoordinates undefined simulateResetPose ();undefined simulateVisibilityChange (XRVisibilityState );state FakeXRInputController simulateInputSourceConnection (FakeXRInputSourceInit ); // Hit test extensions:init undefined (setWorld FakeXRWorldInit );world undefined (); // Depth sensing extensions:clearWorld undefined (setDepthSensingData FakeXRDepthSensingDataInit );depthSensingData undefined (); };clearDepthSensingData
Each FakeXRDevice object has an associated device, which is a simulated XR device that it is able to control.
Operations on the FakeXRDevice’s device typically take place on the next animation frame, i.e. they are not immediately observable until a future requestAnimationFrame() callback.
To determine when this frame is, for a given operation, choose a frame based on the following:
- If such an operation is triggered within an XR animation frame:
- Choose the next XR animation frame, whenever it may occur
- If such an operation is triggered outside of an XR animation frame:
- Choose either the next or next-to-next XR animation frame. The precise choice is up to the user agent and may be dependent on the exact timing of these events.
NOTE: The reason we defer an extra frame when there are pending animation frame callbacks is to avoid having to deal with potential race conditions when the device is ready to trigger an animation frame callback, but has not yet. In practice, this means that tests should be written so that they wait until they have performed all such operations before calling the next requestAnimationFrame(), and in case they are running outside of an XR animation frame, should always wait two frames before expecting any updates to take effect.
-
Let l be an empty list
-
let offset be `0`
-
For each view in views:
-
Let v be the result of running parse a view on view and offset.
-
Append v to l.
-
Increase offset by `1`.
-
-
Return l.
setViews(views, secondaryViews) method performs the following steps:
-
On the next animation frame, run the following steps:
-
Let p be the result of running parse a list of views on views.
-
Set device’s list of primary views to p.
-
If secondaryViews is set, let s be the result of running parse a list of views on secondaryViews.
-
Set device’s list of secondary views to s.
-
-
When disconnect() method is called, perform the following steps:
-
Remove device from the
xr’s list of immersive XR devices as if it were disconnected. -
If the inline XR device is equal to the
FakeXRDevice, reset it to the default inline XR device.
setViewerOrigin(origin, emulatedPosition) performs the following steps:
-
Let o be the result of running parse a rigid transform on origin.
-
On the next animation frame, perform the following steps:
-
Set device’s viewer origin to o.
-
Set device’s emulated position boolean to emulatedPosition.
-
The clearViewerOrigin() method will, on the next animation frame, set device’s viewer origin to null.
The simulateVisibilityChange(state) method will, as soon as possible, set device’s visibility state to state.
setFloorOrigin(origin) performs the following steps:
-
Let o be the result of running parse a rigid transform on origin.
-
On the next animation frame, set device’s floor origin to o.
The clearFloorOrigin() method will, on the next animation frame, set device’s floor origin to null.
setBoundsGeometry(boundsCoordinates) performs the following steps:
-
If boundsCoordinates has fewer than 3 elements, throw a
TypeError. -
On the next animation frame, set device’s native bounds geometry to boundsCoordinates.
The simulateResetPose() method will, as soon as possible, behave as if the device’s viewer’s native origin had a discontinuity, triggering appropriate reset events.
simulateInputSourceConnection(init) method creates a new simulated XR input source.
When this method is invoked, the user agent MUST run the following steps:
-
Let inputSource be a new simulated XR input source.
-
Set inputSource’s handedness to init’s
handedness. -
Set inputSource’s targetRayMode to init’s
targetRayMode. -
If init’s
gripOriginis set, set inputSource’s gripOrigin to the result of running parse a rigid transform on init’sgripOrigin -
Set inputSource’s pointerOrigin to the result of running parse a rigid transform on init’s
pointerOrigin -
If init’s
supportedButtonsis set, set inputSource’s buttonState to the result of running parse supported buttons on init’ssupportedButtons -
If init’s
selectionClickedis set totrue, run simulate a full primary action on inputSource. -
If init’s
selectionStartedis set totrue, run start a primary action on inputSource. -
By the next animation frame notify
XRSessionof the new XR input source. -
Let c be a new
FakeXRInputControllerobject with {inputSource as inputSource. -
Return c.
5.2. FakeXRInputController
dictionary {FakeXRInputSourceInit required XRHandedness ;handedness required XRTargetRayMode ;targetRayMode required FakeXRRigidTransformInit ;pointerOrigin required sequence <DOMString >;profiles boolean =selectionStarted false ;boolean =selectionClicked false ;sequence <FakeXRButtonStateInit >;supportedButtons FakeXRRigidTransformInit ; };gripOrigin interface {FakeXRInputController undefined setHandedness (XRHandedness );handedness undefined setTargetRayMode (XRTargetRayMode );targetRayMode undefined setProfiles (sequence <DOMString >);profiles undefined setGripOrigin (FakeXRRigidTransformInit ,gripOrigin optional boolean =emulatedPosition false );undefined clearGripOrigin ();undefined setPointerOrigin (FakeXRRigidTransformInit ,pointerOrigin optional boolean =emulatedPosition false );undefined disconnect ();undefined reconnect ();undefined startSelection ();undefined endSelection ();undefined simulateSelect ();undefined setSupportedButtons (sequence <FakeXRButtonStateInit >);supportedButtons undefined updateButtonState (FakeXRButtonStateInit ); };buttonState enum {FakeXRButtonType ,"grip" ,"touchpad" ,"thumbstick" ,"optional-button" };"optional-thumbstick" dictionary {FakeXRButtonStateInit required FakeXRButtonType ;buttonType required boolean ;pressed required boolean ;touched required float ;pressedValue float = 0.0;xValue float = 0.0; };yValue
Each FakeXRInputController object has an associated inputSource, which is a simulated XR input source that it is able to control.
Since user agents may opt to send input events on a per-frame basis, the results of all FakeXRInputController methods and simulateInputSourceConnection() are not guaranteed to be visible (via, e.g. inputSources or oninputsourceschange events) until the next animation frame.
-
If primaryActionStarted is true, abort these steps.
-
Set primaryActionStarted to true.
-
By the next animation frame indicate to the
XRSessionthat the corresponding XR input source’s primary action has started.
-
If primaryActionStarted is false, abort these steps.
-
Set primaryActionStarted to false.
-
By the next animation frame indicate to the
XRSessionthat the corresponding XR input source’s primary action has stopped.
-
Let current be the current value of primaryActionStarted.
-
Run start a primary action on source
-
Run stop a primary action on source
-
If current is
truerun start a primary action on source
Note: If a gamepad is attached to the simulated XR input source, then running start a primary action or stop a primary action should also ensure that the primary input’s corresponding gamepad button is updated accordingly.
Note: If both start a primary action and stop a primary action are run in the same frame, then by the next animation frame It is expected that onselect and onselectend events will fire.
FakeXRButtonStateInits, buttons run the following steps:
-
Let l be an empty list of
FakeXRButtonStateInits -
For each button in buttons:
-
If l does not contain a
FakeXRButtonStateInitwhosebuttonTypematches button’sbuttonType, append button to l.
-
-
Return l
The setHandedness(handedness) method will, by the next animation frame, set inputSource’s handedness to handedness.
The setTargetRayMode(targetRayMode) method will, by the next animation frame, set inputSource’s targetRayMode to targetRayMode.
The setProfiles(profiles) method will, by the next animation frame, set inputSource’s profiles to profiles.
The setGripOrigin(gripOrigin) method will, by the next animation frame, set inputSource’s gripOrigin to the result of running parse a rigid transform on gripOrigin.
The clearGripOrigin() method will, by the next animation frame, set inputSource’s gripOrigin to null.
The setPointerOrigin(pointerOrigin) method will, by the next animation frame, set inputSource’s pointerOrigin to the result of running parse a rigid transform on pointerOrigin.
disconnect() method will run the following steps:
-
If inputSource’s connectionState is
false, abort these steps. -
Set inputSource’s connectionState to
false. -
By the next animation frame, notify the
XRSessionthat this XR input source has been removed.
reconnect() method will run the following steps:
-
If inputSource’s connectionState is
true, abort these steps. -
Set inputSource’s connectionState to
true. -
By the next animation frame, notify the
XRSessionthat this XR input source has been added.
The startSelection() method will run start a primary action on inputSource.
The endSelection() method will run stop a primary action on inputSource.
The simulateSelect() method will run simulate a full primary action on inputSource.
The setSupportedButtons(supportedButtons) will, by the next animation frame, set inputSource’s buttonState to the result of running parse supported buttons on supportedButtons.
Note: As user agents may recreate the XRInputSource or gamepad objects on buttons being changed, this method SHOULD NOT be used to simulate changes to button state.
updateButtonState(buttonState) will run the following steps:
-
Let validState equal the results of running validate a button state on buttonState.
-
Let foundState be
null. -
For every state in inputSource’s buttonState array:
-
If state’s
buttonTypematches buttonState’sbuttonType:-
Set foundState to a reference of state
-
Break out of this loop
-
-
-
If foundState is
nullthrow aNotFoundError -
Update foundState’s attributes in inputSource’s buttonState to match those of validState. Note: If
buttonTypeisgrip, then XR input source’s primary squeeze action should be updated.
FakeXRButtonStateInit buttonState run the following steps:
-
Let validState equal buttonState.
-
If
pressedValueis less than0.0, throw aTypeError. -
If
pressedValueis greater than0.0andtouchedisfalsethrow aTypeError. -
If
buttonTypeis not one of:"touchpad","thumbstick", or"optional-thumbstick": -
Return validState.
6. Hit test extensions
The hit test extensions for test API SHOULD be implemented by all user agents that implement WebXR Hit Test Module.
dictionary {FakeXRWorldInit required sequence <FakeXRRegionInit >; };hitTestRegions
FakeXRWorldInit dictionary describes the state of the world that will be used when computing hit test results on a FakeXRDevice.
hitTestRegions contains a collection of FakeXRRegionInits that are used to describe specific regions of the fake world. The order of the regions does not matter.
dictionary {FakeXRRegionInit required sequence <FakeXRTriangleInit >;faces required FakeXRRegionType ; };type
FakeXRRegionInit dictionary describes the contents of a specific region of the world.
faces contains a collection of FakeXRTriangleInits that enumerate all the faces contained by the region. The order of the faces does not matter.
type contains a type of the region that will be used during computation of hit test results.
dictionary {FakeXRTriangleInit required sequence <DOMPointInit >; // size = 3 };vertices
FakeXRTriangleInit dictionary describes a single face of a region.
vertices contains a collection of DOMPointInits that comprise the face. The face will be considered as solid when computing hit test results and as such, the winding order of the vertices does not matter.
enum {FakeXRRegionType ,"point" ,"plane" };"mesh"
FakeXRRegionType enum is used to describe a type of the world region.
7. DOM overlay extensions
The DOM Overlay extensions for test API SHOULD be implemented by all user agents that implement WebXR DOM Overlay Module.
partial interface FakeXRInputController {undefined setOverlayPointerPosition (float ,x float ); };y
When setOverlayPointerPosition(x, y) is called, it sets a position within the DOM overlay in DOM coordinates for the next XR animation frame, and is cleared after that frame. It is intended to be used along with a primary action for that frame, simulating that the user is interacting with the DOM overlay. The UA will emit a beforexrselect event at this location before generating XR select events.
8. Anchors extensions
The anchors extensions for test API SHOULD be implemented by all user agents that implement WebXR Anchors.
dictionary {FakeXRAnchorCreationParameters FakeXRRigidTransformInit ;requestedAnchorOrigin boolean ; };isAttachedToEntity callback =FakeXRAnchorCreationCallback Promise <boolean > (FakeXRAnchorCreationParameters ,parameters FakeXRAnchorController );anchorController partial interface FakeXRDevice {undefined (setAnchorCreationCallback FakeXRAnchorCreationCallback ?); };callback
The FakeXRAnchorCreationCallback callback can be used by the Web Platform Tests to control the result of a call to create an anchor, and to be able to subsequently control the newly created anchor.
The FakeXRDevice interface is extended with internal anchorCreationCallback, initially set to null. When the device receives a request to create an anchor, it MUST run the determine if the anchor creation succeeded algorithm.
In order to determine if the anchor creation succeeded, the FakeXRDevice device MUST run the following steps:
-
If the device’s anchorCreationCallback is
null, returnfalseand abort these steps. -
Let promise be the result of invoking anchorCreationCallback with parameters set so that they reflect the parameters passed to anchor creation request.
-
React to promise:
-
If promise was fulfilled with value v, then return v and abort these steps.
-
If promise was rejected, then return
falseand abort these steps.
-
The WPTs can set the anchor creation callback by calling setAnchorCreationCallback(callback).
The requestedAnchorOrigin attribute represents a transform expressed relative to base reference space used by the device.
The isAttachedToEntity attribute will be set to true if the created anchor should be treated as attached to some entity. If so, the tests could emulate entity changing location by appropriately controlling the anchor via anchorController.
The anchorController parameter passed in to FakeXRAnchorCreationCallback can be used to update the state of the anchor, assuming that the creation request was deemed successful. Tests SHOULD store it and issue commands to it for the entire duration of controlled anchor’s lifetime.
interface {FakeXRAnchorController readonly attribute boolean ; // Controlling anchor state:deleted undefined ();pauseTracking undefined ();resumeTracking undefined (); // Controlling anchor location:stopTracking undefined (setAnchorOrigin FakeXRRigidTransformInit ); };anchorOrigin
Successfully created anchors can be controlled by the test through the use of FakeXRAnchorController interface.
The FakeXRAnchorController has an associated internal anchor origin, which is a FakeXRRigidTransformInit describing the current state of the anchor’s native origin.
The deleted attribute will be set to true when the application has invoked an delete() method on the anchor - in that case, the changes to the fake anchor controller will be ignored.
The pauseTracking() method can be used by the tests to signal that the controlled anchor is temporarily untracked (i.e. its location will be unknown). Calling this method does not modify anchor origin of the controller.
The resumeTracking() method can be used by the tests to signal that the controlled anchor should have its tracking resumed, if it was temporarily untracked. Calling this method does not modify anchor origin of the controller.
The stopTracking() method can be used by the tests to signal that the controlled anchor is no longer tracked and that anchor tracking will not be resumed. After calling this method, the other calls on anchor controller will be ignored.
The setAnchorOrigin(anchorOrigin) method can be used to set the controller’s anchor origin. Tests can use this method to simulate updates in anchor pose.
9. Lighting estimation extensions
The lighting estimation extensions for test API SHOULD be implemented by all user agents that implement WebXR Lighting Estimation.
dictionary {FakeXRLightEstimateInit required sequence <float >;sphericalHarmonicsCoefficients DOMPointInit ;primaryLightDirection DOMPointInit ; };primaryLightIntensity partial interface FakeXRDevice {undefined setLightEstimate (FakeXRLightEstimateInit ); };init
The FakeXRDevice is extended with internal light estimate which is a FakeXRLightEstimateInit, used to supply data for any requested XRLightEstimate.
setLightEstimate(init) method is invoked on FakeXRDevice device, run the following steps:
-
Let c be init’s
sphericalHarmonicsCoefficients. -
If c does not have 27 elements, throw a
TypeErrorand abort these steps. -
Let d be init’s
primaryLightDirection. -
If d is set and d’s
wvalue does not equal0, throw aTypeErrorand abort these steps. -
Let i be init’s
primaryLightIntensity. -
If i is set and i’s
wvalue does not equal1, throw aTypeErrorand abort these steps. -
Set device’s light estimate to init by the next animation frame.
10. Depth sensing extensions
The depth sensing extensions for test API SHOULD be implemented by all user agents that implement WebXR Depth Sensing Module.
The FakeXRDevice is extended with internal depth sensing data which is a FakeXRDepthSensingDataInit, used to supply data for requests to native depth sensing.
dictionary {FakeXRDepthConfigurationSupport sequence <XRDepthType >;depthTypes sequence <XRDepthFormat >;depthFormats sequence <XRDepthUsage >; };depthUsages
The FakeXRDepthConfigurationSupport dictionary is used to define the native depth sensing capabilities of a simulated XR device. Missing or empty sequences for depthTypes, depthFormats, or depthUsages indicate that all possible values for that respective enumeration are supported by the simulated XR device. If a User Agent does not support a particular value for any real device that it supports, it SHOULD ignore the presence of that value in any of these lists, in order to generate a more appropriate failure.
Note: For simplicity, the simulated XR device is presumed to support the cross-product of all supported types, formats, and usages. There is currently no mechanism in this test API to specify support for only specific combinations (e.g., a particular format and type only with a particular usage).
dictionary {FakeXRDepthSensingDataInit required ArrayBuffer ;depthData required XRDepthFormat ;depthFormat required FakeXRRigidTransformInit ;normDepthBufferFromNormView required float ;rawValueToMeters required unsigned long ;width required unsigned long ;height sequence <float >;projectionMatrix FakeXRRigidTransformInit ; };viewOffset
FakeXRDepthSensingDataInit dictionary describes the state of the depth sensing data that should be used when returning latest depth information in creating a CPU depth information instance and creating a GPU depth information instance algorithms. All keys present in FakeXRDepthSensingDataInit correspond to the data required to be returned by native depth sensing capabilities of the device.
depthData corresponds to the desired depth buffer that is to be set on native depth information returned from querying the native device. Not setting depthData key in the dictionary signals that the returned native depth information should be null.
depthFormat indicates the XRDepthFormat of the data set in depthData.
normDepthBufferFromNormView corresponds to the desired depth coordinates transformation matrix that is to be set on native depth information returned from querying the native device.
rawValueToMeters corresponds to the desired conversion factor that is to be set on native depth information returned from querying the native device.
width and height correspond to the desired dimensions of the depth buffer that are to be set on native depth information returned from querying the native device.
projectionMatrix is an optional 16-element sequence of floats representing a projection matrix. If present, this matrix is intended to define the projection matrix for the sensor’s XRViewGeometry. If not present, the sensor geometry’s projection matrix is assumed to be aligned with the projection matrix of the XRViewGeometry of the view for which the depth information is being created.
viewOffset is an optional FakeXRRigidTransformInit. If present, this transform is intended to define the view offset for the sensor’s XRViewGeometry, relative to the base reference space. If not present, the sensor geometry’s transform is assumed to be aligned with the view offset of the XRViewGeometry of the view for which the depth information is being created.
When the setDepthSensingData() method is invoked on FakeXRDevice device with depthSensingData, run the following steps:
-
If depthSensingData’s
depthDataisnull, throw aTypeErrorand abort these steps. -
If depthSensingData’s
projectionMatrixis set and its size is not 16, throw aTypeErrorand abort these steps. -
If depthSensingData’s
viewOffsetis set, run parse a rigid transform on depthSensingData’sviewOffset. -
Set device’s depth sensing data to depthSensingData.
When the clearDepthSensingData() method is invoked on FakeXRDevice device, run the following steps:
-
Set device’s depth sensing data to
null.
11. Raw camera access extensions
The raw camera access extensions for test API SHOULD be implemented by all user agents that implement WebXR Raw Camera Access Module.
The FakeXRViewInit dictionary is extended with cameraImageInit dictionary of type FakeXRDeviceResolution. This dictionary carries information about the camera image, and is intended to affect the camera image variable in obtain camera algorithm. If the cameraImageInit key is not present in the FakeXRViewInit dictionary, the obtain camera algorithm should treat this as null camera image (and thus the algorithm will return null).
dictionary {FakeXRCameraImage required long ;width required long ;height Uint32Array ; };pixels
The width controls the width of the camera image buffer in obtain camera algorithm.
The height controls the height of the camera image buffer in obtain camera algorithm.
The pixels control the camera image contents in obtain camera algorithm. The pixels will be used to initialize the camera image texture.
The camera image will be initialized as if by a call to gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels), where width, height, and pixels are, respectively, width, height, and pixels. In case pixels key is not present in the dictionary, the behavior would be as if a call to gl.texImage2D() variant that omits the pixels parameter was made.
Any time a simulated XR device’s list of primary views and list of secondary views is set, the user agent MUST verify that the camera images associated with the views present across both of those lists are all equal to each other. Camera images are considered equal when their widths and heights are equal, and their pixels are the same instance (if present). If they are not equal, the user agent MUST throw an error from within the algorithm that attempted to set them.