Commit de85fa73 authored by Luis G Garcia's avatar Luis G Garcia Committed by Commit Bot

WebXR: Add more camera access instrumentation tests.

Add logging for sync tokens in three locations.

New Tests:
- Test session failure if WebXRIncubations not enabled and camera access
is requested.
- Test session failure if permissions rejected.
- Test camera image texture null if feature not requested.

New Disabled Test:
- Test camera image texture lifetime limited to one frame.


Bug: 1115167
Change-Id: I602b8fbfdd4ff39c189364ef5b7670b8c6228211
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2342211
Commit-Queue: Luis Garcia <luisggarcia@google.com>
Reviewed-by: default avatarPiotr Bialecki <bialpio@chromium.org>
Reviewed-by: default avatarKlaus Weidner <klausw@chromium.org>
Reviewed-by: default avatarBrian Sheedy <bsheedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797880}
parent 8aaf5430
......@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.vr;
import static org.junit.Assert.assertTrue;
import static org.chromium.chrome.browser.vr.WebXrArTestFramework.PAGE_LOAD_TIMEOUT_S;
import static org.chromium.chrome.browser.vr.XrTestFramework.POLL_TIMEOUT_SHORT_MS;
......@@ -22,11 +24,13 @@ import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
import org.chromium.base.test.params.ParameterSet;
import org.chromium.base.test.params.ParameterizedRunner;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.MinAndroidSdkLevel;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.vr.rules.ArPlaybackFile;
import org.chromium.chrome.browser.vr.rules.XrActivityRestriction;
import org.chromium.chrome.browser.vr.util.ArTestRuleUtils;
import org.chromium.chrome.browser.vr.util.PermissionUtils;
import org.chromium.chrome.test.ChromeActivityTestRule;
import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
......@@ -38,10 +42,8 @@ import java.util.concurrent.Callable;
*/
@RunWith(ParameterizedRunner.class)
@UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
"enable-features=WebXRIncubations,LogJsConsoleMessages"})
@MinAndroidSdkLevel(Build.VERSION_CODES.O)
// TODO(https://crbug.com/1112356) Change this to Build.VERSION_CODES.N once N support is added.
@MinAndroidSdkLevel(Build.VERSION_CODES.O)
public class WebXrArCameraAccessTest {
@ClassParameter
private static List<ParameterSet> sClassParams =
......@@ -68,8 +70,11 @@ public class WebXrArCameraAccessTest {
@Test
@MediumTest
@XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
"enable-features=WebXRIncubations,LogJsConsoleMessages"})
@ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
public void testCameraAccessImageTextureNotNull() {
public void
testCameraAccessImageTextureNotNull() {
mWebXrArTestFramework.loadFileAndAwaitInitialization(
"webxr_test_camera_access", PAGE_LOAD_TIMEOUT_S);
mWebXrArTestFramework.enterSessionWithUserGestureOrFail();
......@@ -85,8 +90,11 @@ public class WebXrArCameraAccessTest {
@Test
@MediumTest
@XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
"enable-features=WebXRIncubations,LogJsConsoleMessages"})
@ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
public void testConsecutiveCameraAccessImageTexturesNotNull() {
public void
testConsecutiveCameraAccessImageTexturesNotNull() {
mWebXrArTestFramework.loadFileAndAwaitInitialization(
"webxr_test_camera_access", PAGE_LOAD_TIMEOUT_S);
mWebXrArTestFramework.enterSessionWithUserGestureOrFail();
......@@ -103,8 +111,11 @@ public class WebXrArCameraAccessTest {
@Test
@MediumTest
@XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
"enable-features=WebXRIncubations,LogJsConsoleMessages"})
@ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
public void testCameraAccessImageTextureCanBeDeleted() {
public void
testCameraAccessImageTextureCanBeDeleted() {
mWebXrArTestFramework.loadFileAndAwaitInitialization(
"webxr_test_camera_access", PAGE_LOAD_TIMEOUT_S);
mWebXrArTestFramework.enterSessionWithUserGestureOrFail();
......@@ -113,4 +124,96 @@ public class WebXrArCameraAccessTest {
mWebXrArTestFramework.waitOnJavaScriptStep();
mWebXrArTestFramework.endTest();
}
/**
* Test that if the WebXRIncubations flag is not enabled, and the camera-access feature is
* requested, session creation will fail.
*/
@Test
@MediumTest
@XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
@CommandLineFlags.
Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-features=LogJsConsoleMessages"})
@ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
public void testCameraAccessSessionCreationFailsWhenWebXrIncubationsFlagDisabled() {
mWebXrArTestFramework.loadFileAndAwaitInitialization(
"webxr_test_camera_access", PAGE_LOAD_TIMEOUT_S);
mWebXrArTestFramework.runJavaScriptOrFail(
"sessionTypeToRequest = sessionTypes.AR", PAGE_LOAD_TIMEOUT_S);
mWebXrArTestFramework.enterSessionWithUserGesture();
mWebXrArTestFramework.pollJavaScriptBooleanOrFail(
"sessionInfos[sessionTypes.AR].error !== null", POLL_TIMEOUT_SHORT_MS);
mWebXrArTestFramework.pollJavaScriptBooleanOrFail(
"sessionInfos[sessionTypes.AR].currentSession === null", POLL_TIMEOUT_SHORT_MS);
}
/**
* Test that if the chrome camera permission is rejected, session creation will fail.
*/
@Test
@MediumTest
@XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
"enable-features=WebXRIncubations,LogJsConsoleMessages"})
@ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
public void
testCameraAccessSessionCreationFailsWhenPermissionRejected() {
mWebXrArTestFramework.loadFileAndAwaitInitialization(
"webxr_test_camera_access", PAGE_LOAD_TIMEOUT_S);
mWebXrArTestFramework.runJavaScriptOrFail(
"sessionTypeToRequest = sessionTypes.AR", PAGE_LOAD_TIMEOUT_S);
mWebXrArTestFramework.enterSessionWithUserGesture();
assertTrue(mWebXrArTestFramework.shouldExpectPermissionPrompt());
PermissionUtils.waitForPermissionPrompt();
PermissionUtils.denyPermissionPrompt();
mWebXrArTestFramework.pollJavaScriptBooleanOrFail(
"sessionInfos[sessionTypes.AR].error !== null", POLL_TIMEOUT_SHORT_MS);
mWebXrArTestFramework.pollJavaScriptBooleanOrFail(
"sessionInfos[sessionTypes.AR].currentSession === null", POLL_TIMEOUT_SHORT_MS);
}
/**
* Test that if the camera-access feature is not requested, getCameraTexture() does not return a
* texture.
*/
@Test
@MediumTest
@XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
"enable-features=WebXRIncubations,LogJsConsoleMessages"})
@ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
public void
testCameraAccessImageTextureNullWhenFeatureNotRequested() {
mWebXrArTestFramework.loadFileAndAwaitInitialization(
"webxr_test_no_camera_access", PAGE_LOAD_TIMEOUT_S);
mWebXrArTestFramework.enterSessionWithUserGestureOrFail();
mWebXrArTestFramework.runJavaScriptOrFail(
"stepConfirmCameraTextureIsNull()", POLL_TIMEOUT_SHORT_MS);
mWebXrArTestFramework.waitOnJavaScriptStep();
mWebXrArTestFramework.endTest();
}
/**
* Test the texture lifetime of camera image textures.
*/
@Test
@MediumTest
@DisabledTest(message = "https://www.crbug.com/1115167")
@XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
"enable-features=WebXRIncubations,LogJsConsoleMessages"})
@ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
public void
testCameraAccessImageTextureLifetime() {
mWebXrArTestFramework.loadFileAndAwaitInitialization(
"webxr_test_camera_access", PAGE_LOAD_TIMEOUT_S);
mWebXrArTestFramework.enterSessionWithUserGestureOrFail();
mWebXrArTestFramework.runJavaScriptOrFail(
"stepCheckCameraTextureLifetimeLimitedToOneFrame()", POLL_TIMEOUT_SHORT_MS);
mWebXrArTestFramework.waitOnJavaScriptStep();
mWebXrArTestFramework.endTest();
}
}
\ No newline at end of file
......@@ -258,6 +258,12 @@ gpu::MailboxHolder ArImageTransport::TransferCameraImageFrame(
// command buffer stream.
DCHECK(camera_image_shared_buffer->mailbox_holder.sync_token.HasData());
WaitSyncToken(camera_image_shared_buffer->mailbox_holder.sync_token);
DVLOG(3) << __func__
<< ": "
"camera_image_shared_buffer->mailbox_holder.sync_"
"token="
<< camera_image_shared_buffer->mailbox_holder.sync_token
.ToDebugString();
}
// Sanity checks for the camera image buffer.
DCHECK(!camera_image_shared_buffer->mailbox_holder.mailbox.IsZero());
......@@ -293,6 +299,9 @@ gpu::MailboxHolder ArImageTransport::TransferCameraImageFrame(
mailbox_bridge_->GenSyncToken(
&camera_image_shared_buffer->mailbox_holder.sync_token);
DVLOG(3)
<< __func__ << ": camera_image_shared_buffer->mailbox_holder.sync_token="
<< camera_image_shared_buffer->mailbox_holder.sync_token.ToDebugString();
return camera_image_shared_buffer->mailbox_holder;
}
......
......@@ -9,15 +9,17 @@ Tests that AR camera access returns non-empty GLTexture.
<canvas id="webgl-canvas"></canvas>
<script src="../../../../../../third_party/blink/web_tests/resources/testharness.js"></script>
<script src="../resources/webxr_e2e.js"></script>
<script src="../resources/webxr_boilerplate.js"></script>
<script>var shouldAutoCreateNonImmersiveSession = false;</script>
<script>var immersiveArSessionInit = { requiredFeatures: ['camera-access'] };</script>
<script src="../resources/webxr_boilerplate.js"></script>
<!-- Required features must be set after importing webxr_boilerplate.js to avoid overwrite -->
<script>var immersiveArSessionInit = { requiredFeatures: ['camera-access'] };</script>
<script>
setup({single_test: true});
let numPosesFound = 0;
let cameraImageTexture = null;
let ranAtLeastOnce = false;
let pixels = null;
function stepStartStoringCameraTexture(numCalls) {
const webglCanvas = document.getElementById('webgl-canvas');
......@@ -28,21 +30,18 @@ Tests that AR camera access returns non-empty GLTexture.
const referenceSpace = sessionInfo.currentRefSpace;
onARFrameCallback = (session, frame) => {
const glBinding = new XRWebGLBinding(session, gl);
const pose = frame.getViewerPose(referenceSpace);
if (pose) {
// Wait several frames to allow the image buffer to be populated by a camera
// texture before attempting to get the camera image texture.
if (numPosesFound >= 10) {
const glBinding = new XRWebGLBinding(session, gl);
for (let view of pose.cameraViews) {
ranAtLeastOnce = true;
// Used to test that multiple consecutive calls will all return non-null textures.
for (let remainingCalls = numCalls; remainingCalls > 0; remainingCalls--) {
cameraImageTexture = glBinding.getCameraImage(frame, view);
if (cameraImageTexture === null) {
onARFrameCallback = null;
assert_unreached("XRWebGLBinding.getCameraImage(...) returned null texture.");
}
assert_not_equals(cameraImageTexture, null, "XRWebGLBinding.getCameraImage(...) returned null texture.");
}
}
}
......@@ -66,9 +65,9 @@ Tests that AR camera access returns non-empty GLTexture.
const referenceSpace = sessionInfo.currentRefSpace;
onARFrameCallback = (session, frame) => {
const glBinding = new XRWebGLBinding(session, gl);
const pose = frame.getViewerPose(referenceSpace);
if (pose) {
const glBinding = new XRWebGLBinding(session, gl);
for (let view of pose.cameraViews) {
ranAtLeastOnce = true;
cameraImageTexture = glBinding.getCameraImage(frame, view);
......@@ -84,6 +83,91 @@ Tests that AR camera access returns non-empty GLTexture.
}
};
}
function stepConfirmCameraTextureIsNull() {
const webglCanvas = document.getElementById('webgl-canvas');
const gl = webglCanvas.getContext('webgl', {
xrCompatible: true
});
const sessionInfo = sessionInfos[sessionTypes.AR];
const referenceSpace = sessionInfo.currentRefSpace;
onARFrameCallback = (session, frame) => {
const pose = frame.getViewerPose(referenceSpace);
if (pose) {
const glBinding = new XRWebGLBinding(session, gl);
for (let view of pose.cameraViews) {
cameraImageTexture = glBinding.getCameraImage(frame, view);
assert_not_equals(cameraImageTexture, null, "XRWebGLBinding.getCameraImage(...) returned null texture.");
}
numPosesFound++;
}
if (numPosesFound > 20) {
onARFrameCallback = null;
done();
}
};
}
// TODO(https://www.crbug.com/1115167): Enable test once pixel reads are working as intended.
function stepCheckCameraTextureLifetimeLimitedToOneFrame() {
const webglCanvas = document.getElementById('webgl-canvas');
const gl = webglCanvas.getContext('webgl', {
xrCompatible: true
});
const sessionInfo = sessionInfos[sessionTypes.AR];
const referenceSpace = sessionInfo.currentRefSpace;
const fb = gl.createFramebuffer();
const attachmentPoint = gl.COLOR_ATTACHMENT0;
const level = 0;
// Assign pixels array non-zero values.
pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);
pixels.fill(1);
onARFrameCallback = (session, frame) => {
const pose = frame.getViewerPose(referenceSpace);
if (pose) {
if (numPosesFound == 10 && pose.cameraViews) {
const glBinding = new XRWebGLBinding(sessionInfo.currentSession, gl);
cameraImageTexture = glBinding.getCameraImage(frame, pose.cameraViews[0]);
gl.bindTexture(gl.TEXTURE_2D, cameraImageTexture);
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, cameraImageTexture, level);
readCameraImageTexturePixels();
let numZeroedRGBAValues = 0;
pixels.forEach(rgbaValue => {
if(rgbaValue == 0) {
numZeroedRGBAValues += 1;
}
});
assert_not_equals(numZeroedRGBAValues, pixels.length, "Camera image texture was already empty.");
}
numPosesFound++;
}
if (numPosesFound == 20)
{
onARFrameCallback = null;
readCameraImageTexturePixels();
pixels.forEach(pixel => assert_equals(pixel, 0));
done();
}
};
}
function readCameraImageTexturePixels () {
if(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE){
gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
assert_equals(gl.getError(), gl.NO_ERROR);
}
}
</script>
</body>
</html>
\ No newline at end of file
<!--
Tests that AR camera access returns empty GLTexture if feature is not requested.
-->
<html>
<head>
<link rel="stylesheet" type="text/css" href="../resources/webxr_e2e.css">
</head>
<body>
<canvas id="webgl-canvas"></canvas>
<script src="../../../../../../third_party/blink/web_tests/resources/testharness.js"></script>
<script src="../resources/webxr_e2e.js"></script>
<script>var shouldAutoCreateNonImmersiveSession = false;</script>
<script src="../resources/webxr_boilerplate.js"></script>
<script>
setup({single_test: true});
let numPosesFound = 0;
let cameraImageTexture = null;
function stepConfirmCameraTextureIsNull() {
const webglCanvas = document.getElementById('webgl-canvas');
const gl = webglCanvas.getContext('webgl', {
xrCompatible: true
});
const sessionInfo = sessionInfos[sessionTypes.AR];
const referenceSpace = sessionInfo.currentRefSpace;
onARFrameCallback = (session, frame) => {
const pose = frame.getViewerPose(referenceSpace);
if (pose) {
for (let view of pose.cameraViews) {
const glBinding = new XRWebGLBinding(session, gl);
cameraImageTexture = glBinding.getCameraImage(frame, view);
assert_equals(cameraImageTexture, null, "XRWebGLBinding.getCameraImage(...) did not return a null texture.");
}
numPosesFound++;
}
if (numPosesFound > 10) {
onARFrameCallback = null;
done();
}
};
}
</script>
</body>
</html>
\ No newline at end of file
......@@ -289,6 +289,8 @@ uint32_t XRWebGLLayer::GetBufferTextureId(
const base::Optional<gpu::MailboxHolder>& buffer_mailbox_holder) {
gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
gl->WaitSyncTokenCHROMIUM(buffer_mailbox_holder->sync_token.GetConstData());
DVLOG(3) << __func__ << ": buffer_mailbox_holder->sync_token="
<< buffer_mailbox_holder->sync_token.ToDebugString();
GLuint texture_id = gl->CreateAndTexStorage2DSharedImageCHROMIUM(
buffer_mailbox_holder->mailbox.name);
return texture_id;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment