зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
357aa1af01
Коммит
c8d0dbbafb
|
@ -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>
|
Загрузка…
Ссылка в новой задаче