blob: 746e3559188c2ecab2437b3713e2c3988bcb82d4 [file] [log] [blame]
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>let additionalChromiumResources = ["../resources/xr-internal-device-mocking.js"];</script>
<script src="/webxr/resources/webxr_util.js"></script>
<script src="/webxr/resources/webxr_test_constants.js"></script>
<script src="/webxr/resources/webxr_test_asserts.js"></script>
<script>
// Because light estimation is not yet in the core webxr spec, this is an internal-chrome only test.
function assert_defined(v, description) {
assert_not_equals(v, undefined, description);
}
// Verifies the structure of |XRLightEstimate|
// Defined in 'third_party/blink/renderer/modules/xr/xr_light_estimate.idl'
function verifyXRLightEstimate(lightEstimate) {
assert_true(lightEstimate instanceof XRLightEstimate);
assert_defined(lightEstimate.sphericalHarmonicsCoefficients, "sphericalHarmonicsCoefficients was not defined on XRLightEstimate");
assert_array_equals(Array.from(lightEstimate.sphericalHarmonicsCoefficients), new Array(9).fill().map((x, i) => [i, i, i]).flat());
assert_defined(lightEstimate.primaryLightDirection, "primaryLightDirection was not defined on XRLightEstimate");
assert_equals(lightEstimate.primaryLightDirection.x, 0);
assert_equals(lightEstimate.primaryLightDirection.y, 1);
assert_equals(lightEstimate.primaryLightDirection.z, 0);
assert_equals(lightEstimate.primaryLightDirection.w, 0);
assert_defined(lightEstimate.primaryLightIntensity, "primaryLightIntensity was not defined on XRLightEstimate");
assert_equals(lightEstimate.primaryLightIntensity.x, 1);
assert_equals(lightEstimate.primaryLightIntensity.y, 1);
assert_equals(lightEstimate.primaryLightIntensity.z, 1);
assert_equals(lightEstimate.primaryLightIntensity.w, 1);
}
// Verifies the behavior of querying reflection cube maps
// Defined in 'third_party/blink/renderer/modules/xr/xr_webgl_binding.idl'
function verifyReflectionCubeMap(session, lightProbe) {
// Currently reflection cube maps only work on WebGL 2.
const gl2Canvas = document.createElement('canvas');
const gl = gl2Canvas.getContext('webgl2');
if (!gl) {
return;
}
return gl.makeXRCompatible().then(() => {
const glBinding = new XRWebGLBinding(session, gl);
assert_true(glBinding instanceof XRWebGLBinding);
assert_defined(glBinding.getReflectionCubeMap, "getReflectionCubeMap was not defined on XRWebGLBinding");
// Bind a different cube map prior to fetching the reflection cube map so we
// can ensure the binding is preserved.
const tmpCubeMap = gl.createTexture();
gl.bindTexture(gl.TEXTURE_CUBE_MAP, tmpCubeMap);
// Make sure we get back a valid cube map
const cubeMap = glBinding.getReflectionCubeMap(lightProbe);
assert_true(cubeMap instanceof WebGLTexture);
const boundCubeMap = gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP);
assert_equals(boundCubeMap, tmpCubeMap);
// Ensure that we can't bind the returned cube map to the TEXTURE_2D bind
// target but can bind it to the TEXTURE_CUBE_MAP bind point. This effectively
// tests that the texture was created as a cube map.
gl.bindTexture(gl.TEXTURE_2D, cubeMap);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, cubeMap);
assert_equals(gl.getError(), gl.NO_ERROR);
});
}
// Verifies the structure of |XRFrame| (as it relates to light estimation)
// for a session that's expected to suppot light estimation.
// Defined in 'third_party/blink/renderer/modules/xr/xr_frame.idl'
function verifyXRLightEstimateExists(t, resolve, count, session, frame, lightProbe, localSpace) {
t.step(() => {
assert_not_equals(count, 0, "Did not get light estimate with a reasonable number of frames");
assert_defined(frame.getLightEstimate, "getLightEstimate was not defined on XRFrame");
const lightEstimate = frame.getLightEstimate(lightProbe);
const lightProbePose = frame.getPose(lightProbe.probeSpace, localSpace);
if (lightEstimate === null) {
// Check if we get a lighting estimate next frame
session.requestAnimationFrame((time, frame) => {
verifyXRLightEstimateExists(t, resolve, count - 1, session, frame, lightProbe, localSpace);
});
} else {
verifyXRLightEstimate(lightEstimate);
// Reflection cube maps may be enabled separately from the other lighting values.
if ('XRWebGLBinding' in window) {
verifyReflectionCubeMap(session, lightProbe).then(() => {
// If the light probe is providing valid results it should also have a
// valid space.
assert_not_equals(lightProbePose, null);
resolve();
});
} else {
// If the light probe is providing valid results it should also have a
// valid space.
assert_not_equals(lightProbePose, null);
resolve();
}
}
});
}
// Verifies the structure of |XRLightProbe|
// Defined in 'third_party/blink/renderer/modules/xr/xr_light_probe.idl'
function verifyXRLightProbe(lightProbe) {
assert_true(lightProbe instanceof XRLightProbe);
assert_true(lightProbe.probeSpace instanceof XRSpace);
assert_not_equals(lightProbe.probeSpace, null);
}
const lightingInformationExistsName = "Ensures lighting estimation feature works when enabled";
function lightingInformationExists(session, fakeDeviceController, t, sessionObjects) {
t.step(() => {
assert_defined(session.requestLightProbe, "requestLightProbe was not defined on XRSession");
});
return new Promise(async (resolve, reject) => {
const lightProbe = await session.requestLightProbe();
verifyXRLightProbe(lightProbe);
const localSpace = await session.requestReferenceSpace("local");
session.requestAnimationFrame((time, frame) => {
verifyXRLightEstimateExists(t, resolve, 10, session, frame, lightProbe, localSpace);
});
});
}
const lightingInformationDoesNotExistName = "Ensure lighting estimation feature does not work when not explicitly enabled";
function lightingInformationDoesNotExist(session, fakeDeviceController, t, sessionObjects) {
t.step(() => {
assert_defined(session.requestLightProbe, "requestLightProbe was not defined on XRSession");
});
return promise_rejects_dom(t, "NotSupportedError", DOMException, session.requestLightProbe());
}
xr_session_promise_test(
lightingInformationExistsName,
lightingInformationExists,
IMMERSIVE_AR_DEVICE,
'immersive-ar',
{ 'requiredFeatures': ['light-estimation'] }
);
xr_session_promise_test(
lightingInformationDoesNotExistName,
lightingInformationDoesNotExist,
IMMERSIVE_AR_DEVICE,
'immersive-ar',
{}
);
</script>