Bug 1691841 [wpt PR 27557] - Add WPTs and minor impl fixes for xr light estimation, a=testonly

Automatic update from web-platform-tests
Add WPTs and minor impl fixes for xr light estimation

Adds WPTs around expected behavior for the WebXR Light Estimation spec.
Also corrects a few cases where getReflectionCubeMap should have thrown
an exception but did not currently.

Change-Id: I3e3393c3911a83bdfc91463cf614e04a31dba009
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2685615
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Reviewed-by: Brandon Jones <bajones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#852756}

--

wpt-commits: 43ead8133543f5d38c0f7aae65770bc1d2e8bad7
wpt-pr: 27557
This commit is contained in:
Alexander Cooper 2021-02-11 16:48:49 +00:00 коммит произвёл moz-wptsync-bot
Родитель 357aa1af01
Коммит c8d0dbbafb
8 изменённых файлов: 425 добавлений и 0 удалений

Просмотреть файл

@ -613,6 +613,68 @@ class MockRuntime {
this.hit_test_source_creation_callback_ = callback;
}
setLightEstimate(fakeXrLightEstimateInit) {
if (!fakeXrLightEstimateInit.sphericalHarmonicsCoefficients) {
throw new TypeError("sphericalHarmonicsCoefficients must be set");
}
if (fakeXrLightEstimateInit.sphericalHarmonicsCoefficients.length != 27) {
throw new TypeError("Must supply all 27 sphericalHarmonicsCoefficients");
}
if (fakeXrLightEstimateInit.primaryLightDirection && fakeXrLightEstimateInit.primaryLightDirection.w != 0) {
throw new TypeError("W component of primaryLightDirection must be 0");
}
if (fakeXrLightEstimateInit.primaryLightIntensity && fakeXrLightEstimateInit.primaryLightIntensity.w != 1) {
throw new TypeError("W component of primaryLightIntensity must be 1");
}
// If the primaryLightDirection or primaryLightIntensity aren't set, we need to set them
// to the defaults that the spec expects. ArCore will either give us everything or nothing,
// so these aren't nullable on the mojom.
if (!fakeXrLightEstimateInit.primaryLightDirection) {
fakeXrLightEstimateInit.primaryLightDirection = { x: 0.0, y: 1.0, z: 0.0, w: 0.0 };
}
if (!fakeXrLightEstimateInit.primaryLightIntensity) {
fakeXrLightEstimateInit.primaryLightIntensity = { x: 0.0, y: 0.0, z: 0.0, w: 1.0 };
}
let c = fakeXrLightEstimateInit.sphericalHarmonicsCoefficients;
this.light_estimate_ = {
lightProbe: {
// XRSphereicalHarmonics
sphericalHarmonics: {
coefficients: [
{ red: c[0], green: c[1], blue: c[2] },
{ red: c[3], green: c[4], blue: c[5] },
{ red: c[6], green: c[7], blue: c[8] },
{ red: c[9], green: c[10], blue: c[11] },
{ red: c[12], green: c[13], blue: c[14] },
{ red: c[15], green: c[16], blue: c[17] },
{ red: c[18], green: c[19], blue: c[20] },
{ red: c[21], green: c[22], blue: c[23] },
{ red: c[24], green: c[25], blue: c[26] }
]
},
// Vector3dF
mainLightDirection: {
x: fakeXrLightEstimateInit.primaryLightDirection.x,
y: fakeXrLightEstimateInit.primaryLightDirection.y,
z: fakeXrLightEstimateInit.primaryLightDirection.z
},
// RgbTupleF32
mainLightIntensity: {
red: fakeXrLightEstimateInit.primaryLightIntensity.x,
green: fakeXrLightEstimateInit.primaryLightIntensity.y,
blue: fakeXrLightEstimateInit.primaryLightIntensity.z
}
}
}
}
// Helper methods
getNonImmersiveDisplayInfo() {
const displayInfo = this.getImmersiveDisplayInfo();
@ -786,6 +848,7 @@ class MockRuntime {
renderingTimeRatio: 0,
stageParameters: this.stageParameters_,
stageParametersId: this.stageParametersId_,
lightEstimationData: this.light_estimate_
};
this.next_frame_id_++;

Просмотреть файл

@ -0,0 +1,57 @@
<!DOCTYPE html>
<body>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="../resources/webxr_util.js"></script>
<script src="../resources/webxr_test_constants.js"></script>
<script>
let testName = "getLightEstimate rejects if probe is from wrong session";
let testFunction = (session, controller, t, sessionObjects) => new Promise((resolve) => {
let staleLightProbe = null;
let newSession = null;
function onFrame(time, frame) {
t.step(() => {
// Attempting to get a lightEstimate with a probe created for a
// different session should throw an exception.
assert_throws_dom('InvalidStateError', () => frame.getLightEstimate(staleLightProbe));
});
// Cleanup the new session we made and then resolve.
resolve(newSession.end());
}
// Request a default lightProbe
let probeInit = {reflectionFormat: session.preferredReflectionFormat };
session.requestLightProbe(probeInit).then((probe) => {
staleLightProbe = probe;
return session.end();
}).then(() => {
// Need to request a new session.
navigator.xr.test.simulateUserActivation( () => {
navigator.xr.requestSession('immersive-ar', {'requiredFeatures': ['light-estimation']})
.then((session2) => {
let glLayer = new XRWebGLLayer(session2, sessionObjects.gl);
glLayer.context = sessionObjects.gl;
// Session must have a baseLayer or frame requests will be ignored.
session2.updateRenderState({
baseLayer: glLayer
});
newSession = session2;
newSession.requestAnimationFrame(onFrame);
});
});
});
});
xr_session_promise_test(
testName,
testFunction,
IMMERSIVE_AR_DEVICE,
'immersive-ar',
{'requiredFeatures': ['light-estimation']});
</script>
</body>

Просмотреть файл

@ -0,0 +1,47 @@
<!DOCTYPE html>
<body>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="../resources/webxr_util.js"></script>
<script src="../resources/webxr_test_constants.js"></script>
<script>
let testName = "Cannot get XrLightEstimate from stale frame";
let testFunction = (session, controller, t) => new Promise((resolve) => {
let lightProbe = null;
let staleFrame = null;
function onFrame(time, frame) {
// Try to get the light estimate (even if it's null), it shouldn't throw.
let estimate = frame.getLightEstimate(lightProbe);
staleFrame = frame;
t.step_timeout(afterFrame, 10);
}
function afterFrame() {
t.step(() => {
// Attempting to call a method on the frame outside the callback that
// originally provided it should cause it to throw an exception.
assert_throws_dom('InvalidStateError', () => staleFrame.getLightEstimate(lightProbe));
});
resolve();
}
// Request a default lightProbe
let probeInit = {reflectionFormat: session.preferredReflectionFormat};
session.requestLightProbe(probeInit).then((probe) => {
lightProbe = probe;
session.requestAnimationFrame(onFrame);
});
});
xr_session_promise_test(
testName,
testFunction,
IMMERSIVE_AR_DEVICE,
'immersive-ar', {'requiredFeatures': ['light-estimation']});
</script>
</body>

Просмотреть файл

@ -0,0 +1,104 @@
<!DOCTYPE html>
<body>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="../resources/webxr_util.js"></script>
<script src="../resources/webxr_test_asserts.js"></script>
<script src="../resources/webxr_test_constants.js"></script>
<script>
let testName = "Can get XRLightEstimates during frame";
let fakeDeviceInitParams = IMMERSIVE_AR_DEVICE;
let fakeEstimateCoefficients = [
0.01, 0.02, 0.03,
0.04, 0.05, 0.06,
0.07, 0.08, 0.09,
0.10, 0.11, 0.12,
0.13, 0.14, 0.15,
0.16, 0.17, 0.18,
0.19, 0.20, 0.21,
0.22, 0.23, 0.24,
0.25, 0.26, 0.27
];
let fakeDirectionInit = { x: 1.0, y: 0.0, z: 0.0, w: 0.0 };
let fakeIntensityInit = { x: 0.0, y: 0.0, z: 1.0, w: 1.0 };
let testFunction = (session, controller, t) => new Promise((resolve) => {
let lightProbe = null;
function onFrameWithNoLightEstimation(time, frame) {
let estimate = frame.getLightEstimate(lightProbe);
t.step(() => {
assert_equals(estimate, null);
});
controller.setLightEstimate({
sphericalHarmonicsCoefficients: fakeEstimateCoefficients
});
requestSkipAnimationFrame(session, onFrameWithCoefficients);
}
function onFrameWithCoefficients(time, frame) {
let estimate = frame.getLightEstimate(lightProbe);
t.step(() => {
assert_not_equals(estimate, null);
assert_equals(estimate.sphericalHarmonicsCoefficients.length, 27);
assert_point_approx_equals(estimate.primaryLightDirection, { x: 0.0, y: 1.0, z: 0.0, w: 0.0 });
assert_point_approx_equals(estimate.primaryLightIntensity, { x: 0.0, y: 0.0, z: 0.0, w: 1.0 });
});
controller.setLightEstimate({
sphericalHarmonicsCoefficients: fakeEstimateCoefficients,
primaryLightDirection: fakeDirectionInit,
});
requestSkipAnimationFrame(session, onFrameWithDirection);
}
function onFrameWithDirection(time, frame) {
let estimate = frame.getLightEstimate(lightProbe);
t.step(() => {
assert_not_equals(estimate, null);
assert_equals(estimate.sphericalHarmonicsCoefficients.length, 27);
assert_point_approx_equals(estimate.primaryLightDirection, fakeDirectionInit);
assert_point_approx_equals(estimate.primaryLightIntensity, { x: 0.0, y: 0.0, z: 0.0, w: 1.0 });
});
controller.setLightEstimate({
sphericalHarmonicsCoefficients: fakeEstimateCoefficients,
primaryLightDirection: fakeDirectionInit,
primaryLightIntensity: fakeIntensityInit
});
requestSkipAnimationFrame(session, onFrameWithDirectionAndIntensity);
}
function onFrameWithDirectionAndIntensity(time, frame) {
let estimate = frame.getLightEstimate(lightProbe);
t.step(() => {
assert_not_equals(estimate, null);
assert_equals(estimate.sphericalHarmonicsCoefficients.length, 27);
assert_point_approx_equals(estimate.primaryLightDirection, fakeDirectionInit);
assert_point_approx_equals(estimate.primaryLightIntensity, fakeIntensityInit);
});
resolve();
}
// Request a default lightProbe
session.requestLightProbe({reflectionFormat: session.preferredReflectionFormat }).then((probe) => {
lightProbe = probe;
session.requestAnimationFrame(onFrameWithNoLightEstimation);
});
});
xr_session_promise_test(
testName,
testFunction,
IMMERSIVE_AR_DEVICE,
'immersive-ar', {'requiredFeatures': ['light-estimation']});
</script>
</body>

Просмотреть файл

@ -0,0 +1,21 @@
<!DOCTYPE html>
<body>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="../resources/webxr_util.js"></script>
<script src="../resources/webxr_test_constants.js"></script>
<script>
xr_session_promise_test(
"getLightProbe rejects on an ended session",
(session, controller, t) => {
return session.end().then(() => {
return promise_rejects_dom(t, "InvalidStateError", session.requestLightProbe())
})
},
IMMERSIVE_AR_DEVICE,
'immersive-ar',
{'requiredFeatures': ['light-estimation']});
</script>
</body>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE html>
<body>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="../resources/webxr_util.js"></script>
<script src="../resources/webxr_test_constants.js"></script>
<script>
let fakeDeviceInitParams = IMMERSIVE_AR_DEVICE;
xr_session_promise_test(
"getLightProbe rejects if not enabled on session",
(session, controller, t) => promise_rejects_dom(t, "NotSupportedError", session.requestLightProbe()),
IMMERSIVE_AR_DEVICE,
'immersive-ar');
</script>
</body>

Просмотреть файл

@ -0,0 +1,27 @@
<!DOCTYPE html>
<body>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="../resources/webxr_util.js"></script>
<script src="../resources/webxr_test_constants.js"></script>
<script>
let testName = "Can create valid XRLightProbe objects";
function testFunction(session, controller, t) {
// Request a default lightProbe
let defaultProbe = session.requestLightProbe();
let srgba8Probe = session.requestLightProbe({reflectionFormat: "srgba8"});
let preferredProbe = session.requestLightProbe({reflectionFormat: session.preferredReflectionFormat });
return Promise.all([defaultProbe, srgba8Probe, preferredProbe]);
}
xr_session_promise_test(
testName,
testFunction,
IMMERSIVE_AR_DEVICE,
'immersive-ar', {'requiredFeatures': ['light-estimation']});
</script>
</body>

Просмотреть файл

@ -0,0 +1,88 @@
<!DOCTYPE html>
<body>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="../resources/webxr_util.js"></script>
<script src="../resources/webxr_test_constants.js"></script>
<script>
let testName = "Test that getReflectionCubeMap returns or throws appropriately without a reflection map.";
let testFunction = (session, controller, t, sessionObjects) => new Promise((resolve) => {
let debug = xr_debug.bind(this, 'testFunction');
let lightProbe1 = null;
let binding1 = new XRWebGLBinding(session, sessionObjects.gl);
// Request a default lightProbe
session.requestLightProbe({reflectionFormat: session.preferredReflectionFormat }).then((probe) => {
// Stash and end session.
lightProbe1 = probe;
debug("Querying first pair");
t.step(() => {
assert_equals(
binding1.getReflectionCubeMap(lightProbe1),
null,
"Active binding and light probe shouldn't throw when requesting cube map");
});
return session.end();
}).then(() => {
// Need to request a new session.
navigator.xr.test.simulateUserActivation( () => {
navigator.xr.requestSession('immersive-ar', { 'requiredFeatures': ['light-estimation'] })
.then((newSession) => {
let newBinding = new XRWebGLBinding(newSession, sessionObjects.gl);
newSession.requestLightProbe({ reflectionFormat: newSession.preferredReflectionFormat }).then((newProbe) => {
t.step(() => {
debug("Querying second pair");
assert_equals(
newBinding.getReflectionCubeMap(newProbe),
null,
"Newly created binding and light probe shouldn't throw");
debug("Querying old pair");
assert_throws_dom(
"InvalidStateError",
() => binding1.getReflectionCubeMap(lightProbe1),
"Binding created with an ended session should throw InvalidStateError");
debug("Querying mismatched pair");
assert_throws_dom(
"InvalidStateError",
() => newBinding.getReflectionCubeMap(lightProbe1),
"Querying binding with a probe with a different backing session should throw InvalidStateError");
});
debug("losing context");
// Trigger a context loss and verify that we are unable to get the reflectionCubeMap.
let lose_context_ext = sessionObjects.gl.getExtension('WEBGL_lose_context');
sessionObjects.gl.canvas.addEventListener('webglcontextlost', (ev) => {
ev.preventDefault();
t.step(() => {
assert_throws_dom(
"InvalidStateError",
() => newBinding.getReflectionCubeMap(newProbe),
"Querying for reflection cube map on a binding with context loss should throw InvalidStateError");
});
resolve(newSession.end());
});
lose_context_ext.loseContext();
}); // Request second light probe
}); // Request second session
}); // SimulateUserActivation
}); // .then on session end
}); // testFunction
xr_session_promise_test(
testName,
testFunction,
IMMERSIVE_AR_DEVICE,
'immersive-ar',
{'requiredFeatures': ['light-estimation']});
</script>
</body>