Add webgl2 tests for WebXR (#26038)

This change adds tests to cover a using a WebGL2 XRWebGLLayer for WebXR

Bug: 1087356
Change-Id: I26c262bdd4945a5067c14131ba5d32659f3ffc95
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2460969
Commit-Queue: Patrick To <patrto@microsoft.com>
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
Reviewed-by: Brandon Jones <bajones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#821471}

Co-authored-by: Patrick To <patrto@microsoft.com>
diff --git a/video-rvfc/request-video-frame-callback-before-xr-session.https.html b/video-rvfc/request-video-frame-callback-before-xr-session.https.html
index db662bd..5277fbb 100644
--- a/video-rvfc/request-video-frame-callback-before-xr-session.https.html
+++ b/video-rvfc/request-video-frame-callback-before-xr-session.https.html
@@ -2,7 +2,6 @@
 <html>
 <title>Test that video.rVFC callbacks started before an XRSession work.</title>
 <body>
-    <canvas/>
 </body>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/webxr/anchors/ar_anchor_freefloating_create_move.https.html b/webxr/anchors/ar_anchor_freefloating_create_move.https.html
index af1898c..87f7556 100644
--- a/webxr/anchors/ar_anchor_freefloating_create_move.https.html
+++ b/webxr/anchors/ar_anchor_freefloating_create_move.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/anchors/ar_anchor_freefloating_delay_creation.https.html b/webxr/anchors/ar_anchor_freefloating_delay_creation.https.html
index a2f4387..686eacf 100644
--- a/webxr/anchors/ar_anchor_freefloating_delay_creation.https.html
+++ b/webxr/anchors/ar_anchor_freefloating_delay_creation.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/anchors/ar_anchor_freefloating_failure.https.html b/webxr/anchors/ar_anchor_freefloating_failure.https.html
index 1625538..dd03be0 100644
--- a/webxr/anchors/ar_anchor_freefloating_failure.https.html
+++ b/webxr/anchors/ar_anchor_freefloating_failure.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/anchors/ar_anchor_freefloating_pause_resume_stop.https.html b/webxr/anchors/ar_anchor_freefloating_pause_resume_stop.https.html
index d3cc4c7..6eb6bc7 100644
--- a/webxr/anchors/ar_anchor_freefloating_pause_resume_stop.https.html
+++ b/webxr/anchors/ar_anchor_freefloating_pause_resume_stop.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/anchors/ar_anchor_states.https.html b/webxr/anchors/ar_anchor_states.https.html
index 1872cf5..8369549 100644
--- a/webxr/anchors/ar_anchor_states.https.html
+++ b/webxr/anchors/ar_anchor_states.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/ar-module/xrDevice_requestSession_immersive-ar.https.html b/webxr/ar-module/xrDevice_requestSession_immersive-ar.https.html
index 1be56dd..9984ee5 100644
--- a/webxr/ar-module/xrDevice_requestSession_immersive-ar.https.html
+++ b/webxr/ar-module/xrDevice_requestSession_immersive-ar.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="../resources/webxr_util.js"></script>
   <script src="../resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
   <script>
     xr_session_promise_test(
       "Tests requestSession accepts immersive-ar mode",
diff --git a/webxr/ar-module/xrSession_environmentBlendMode.https.html b/webxr/ar-module/xrSession_environmentBlendMode.https.html
index 28f31da..beff665 100644
--- a/webxr/ar-module/xrSession_environmentBlendMode.https.html
+++ b/webxr/ar-module/xrSession_environmentBlendMode.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="../resources/webxr_util.js"></script>
   <script src="../resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
   <script>
     xr_session_promise_test(
       "Tests environmentBlendMode for an AR device",
diff --git a/webxr/events_input_source_recreation.https.html b/webxr/events_input_source_recreation.https.html
index ecb4b02..f7ef86c 100644
--- a/webxr/events_input_source_recreation.https.html
+++ b/webxr/events_input_source_recreation.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "Input sources are re-created when handedness or target ray mode changes";
diff --git a/webxr/events_input_sources_change.https.html b/webxr/events_input_sources_change.https.html
index 7c784c3..b2a17d4 100644
--- a/webxr/events_input_sources_change.https.html
+++ b/webxr/events_input_sources_change.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "Transient input sources fire events in the right order";
diff --git a/webxr/events_referenceSpace_reset_immersive.https.html b/webxr/events_referenceSpace_reset_immersive.https.html
index 9643bf6..d12d8f7 100644
--- a/webxr/events_referenceSpace_reset_immersive.https.html
+++ b/webxr/events_referenceSpace_reset_immersive.https.html
@@ -3,7 +3,6 @@
 <script src=/resources/testharnessreport.js></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let immersiveTestName = "XRSession resetpose from a device properly fires off " +
diff --git a/webxr/events_referenceSpace_reset_inline.https.html b/webxr/events_referenceSpace_reset_inline.https.html
index b3abcc8..a445886 100644
--- a/webxr/events_referenceSpace_reset_inline.https.html
+++ b/webxr/events_referenceSpace_reset_inline.https.html
@@ -3,7 +3,6 @@
 <script src=/resources/testharnessreport.js></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let nonImmersiveTestName = "XRSession resetpose from a device properly fires off " +
diff --git a/webxr/events_session_select.https.html b/webxr/events_session_select.https.html
index f83d3c4..9b7402d 100644
--- a/webxr/events_session_select.https.html
+++ b/webxr/events_session_select.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "XRInputSources primary input presses properly fires off the "
diff --git a/webxr/events_session_select_subframe.https.html b/webxr/events_session_select_subframe.https.html
index 96fa117..b7615c3 100644
--- a/webxr/events_session_select_subframe.https.html
+++ b/webxr/events_session_select_subframe.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "Ensures that an XRInputSources primary input being pressed and "
diff --git a/webxr/events_session_squeeze.https.html b/webxr/events_session_squeeze.https.html
index 101f1dc..122fe34 100644
--- a/webxr/events_session_squeeze.https.html
+++ b/webxr/events_session_squeeze.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "XRInputSources primary input presses properly fires off the "
diff --git a/webxr/exclusive_requestFrame_nolayer.https.html b/webxr/exclusive_requestFrame_nolayer.https.html
index f76847a..c1c52f0 100644
--- a/webxr/exclusive_requestFrame_nolayer.https.html
+++ b/webxr/exclusive_requestFrame_nolayer.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 let immersiveTestName = "XRSession requestAnimationFrame must fail if the session has "
@@ -21,7 +20,6 @@
   session.updateRenderState({
     baseLayer: null
   });
-  let webglCanvas = document.getElementsByTagName('canvas')[0];
   let gl = sessionObjects.gl;
 
   // Session must have a baseLayer or frame requests will be ignored.
diff --git a/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html b/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html
index f69f943..bd69649 100644
--- a/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html
+++ b/webxr/gamepads-module/xrInputSource_gamepad_disconnect.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="../resources/webxr_util.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "WebXR InputSource's gamepad gets disconnected when the input source is removed";
diff --git a/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html b/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html
index 1ff9dcf..28f3084 100644
--- a/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html
+++ b/webxr/gamepads-module/xrInputSource_gamepad_input_registered.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="../resources/webxr_util.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "WebXR InputSource's gamepad properly registers input";
diff --git a/webxr/getInputPose_handedness.https.html b/webxr/getInputPose_handedness.https.html
index c5c13fd..9dbaf3b 100644
--- a/webxr/getInputPose_handedness.https.html
+++ b/webxr/getInputPose_handedness.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 
diff --git a/webxr/getInputPose_pointer.https.html b/webxr/getInputPose_pointer.https.html
index 30dbe4c..302dc39 100644
--- a/webxr/getInputPose_pointer.https.html
+++ b/webxr/getInputPose_pointer.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 
diff --git a/webxr/getViewerPose_emulatedPosition.https.html b/webxr/getViewerPose_emulatedPosition.https.html
index acba791..7bffaf5 100644
--- a/webxr/getViewerPose_emulatedPosition.https.html
+++ b/webxr/getViewerPose_emulatedPosition.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
 
   <script>
 
diff --git a/webxr/hit-test/ar_hittest_source_cancel.https.html b/webxr/hit-test/ar_hittest_source_cancel.https.html
index 66f22b1..5e7381d 100644
--- a/webxr/hit-test/ar_hittest_source_cancel.https.html
+++ b/webxr/hit-test/ar_hittest_source_cancel.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/hit-test/ar_hittest_subscription_inputSources.https.html b/webxr/hit-test/ar_hittest_subscription_inputSources.https.html
index d419055..dcd1d71 100644
--- a/webxr/hit-test/ar_hittest_subscription_inputSources.https.html
+++ b/webxr/hit-test/ar_hittest_subscription_inputSources.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html b/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html
index f1c223a..465e161 100644
--- a/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html
+++ b/webxr/hit-test/ar_hittest_subscription_refSpaces.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/hit-test/ar_hittest_subscription_states_regular.https.html b/webxr/hit-test/ar_hittest_subscription_states_regular.https.html
index 0678ff5..9f5513f 100644
--- a/webxr/hit-test/ar_hittest_subscription_states_regular.https.html
+++ b/webxr/hit-test/ar_hittest_subscription_states_regular.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/hit-test/ar_hittest_subscription_states_transient.https.html b/webxr/hit-test/ar_hittest_subscription_states_transient.https.html
index accd4bb..e8a83a6 100644
--- a/webxr/hit-test/ar_hittest_subscription_states_transient.https.html
+++ b/webxr/hit-test/ar_hittest_subscription_states_transient.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html b/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html
index e38e9c6..04df132 100644
--- a/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html
+++ b/webxr/hit-test/ar_hittest_subscription_transientInputSources.https.html
@@ -5,7 +5,6 @@
 <script src="../resources/webxr_test_asserts.js"></script>
 <script src="../resources/webxr_test_constants.js"></script>
 <script src="../resources/webxr_test_constants_fake_world.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/navigator_xr_sameObject.https.html b/webxr/navigator_xr_sameObject.https.html
index 56cd65c..2c3ea54 100644
--- a/webxr/navigator_xr_sameObject.https.html
+++ b/webxr/navigator_xr_sameObject.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "Navigator.xr meets [SameObject] requirement";
diff --git a/webxr/render_state_update.https.html b/webxr/render_state_update.https.html
index 2f28d44..3801a42 100644
--- a/webxr/render_state_update.https.html
+++ b/webxr/render_state_update.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE;
diff --git a/webxr/render_state_vertical_fov_immersive.https.html b/webxr/render_state_vertical_fov_immersive.https.html
index 485438c..c09cd7c 100644
--- a/webxr/render_state_vertical_fov_immersive.https.html
+++ b/webxr/render_state_vertical_fov_immersive.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 let testName = "inlineVerticalFieldOfView is set appropriately on immersively sessions";
diff --git a/webxr/render_state_vertical_fov_inline.https.html b/webxr/render_state_vertical_fov_inline.https.html
index 8bf384f..3b33fb1 100644
--- a/webxr/render_state_vertical_fov_inline.https.html
+++ b/webxr/render_state_vertical_fov_inline.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 let testName = "inlineVerticalFieldOfView is set appropriately on inline sessions";
diff --git a/webxr/resources/webxr_util.js b/webxr/resources/webxr_util.js
index aa45e25..fc4ca7d 100644
--- a/webxr/resources/webxr_util.js
+++ b/webxr/resources/webxr_util.js
@@ -13,7 +13,7 @@
 // override this.
 var xr_debug = function(name, msg) {};
 
-function xr_promise_test(name, func, properties) {
+function xr_promise_test(name, func, properties, glContextType, glContextProperties) {
   promise_test(async (t) => {
     // Perform any required test setup:
     xr_debug(name, 'setup');
@@ -49,6 +49,14 @@
     // we can hopefully provide a clearer indication of what went wrong.
     assert_implements(navigator.xr.test, 'missing navigator.xr.test, even after attempted load');
 
+    let gl = null;
+    let canvas = null;
+    if (glContextType) {
+      canvas = document.createElement('canvas');
+      document.body.appendChild(canvas);
+      gl = canvas.getContext(glContextType, glContextProperties);
+    }
+
     // Ensure that any devices are disconnected when done. If this were done in
     // a .then() for the success case, a test that expected failure would
     // already be marked done at the time that runs and the shutdown would
@@ -60,7 +68,7 @@
     });
 
     xr_debug(name, 'main');
-    return func(t);
+    return func(t, gl);
   }, name, properties);
 }
 
@@ -79,80 +87,80 @@
 // A test function which runs through the common steps of requesting a session.
 // Calls the passed in test function with the session, the controller for the
 // device, and the test object.
-// Requires a webglCanvas on the page.
 function xr_session_promise_test(
     name, func, fakeDeviceInit, sessionMode, sessionInit, properties, glcontextPropertiesParam, gllayerPropertiesParam) {
-  let testDeviceController;
-  let testSession;
-  let sessionObjects = {};
   const glcontextProperties = (glcontextPropertiesParam) ? glcontextPropertiesParam : {};
   const gllayerProperties = (gllayerPropertiesParam) ? gllayerPropertiesParam : {};
 
-  const webglCanvas = document.getElementsByTagName('canvas')[0];
-  // We can't use assert_true here because it causes the wpt testharness to treat
-  // this as a test page and not as a test.
-  if (!webglCanvas) {
-    promise_test(async (t) => {
-      Promise.reject('xr_session_promise_test requires a canvas on the page!');
-    }, name, properties);
+  function runTest(t, glContext) {
+    let testSession;
+    let testDeviceController;
+    let sessionObjects = {gl: glContext};
+
+    // Ensure that any pending sessions are ended when done. This needs to
+    // use a cleanup function to ensure proper sequencing. If this were
+    // done in a .then() for the success case, a test that expected
+    // failure would already be marked done at the time that runs, and the
+    // shutdown would interfere with the next test which may have started.
+    t.add_cleanup(async () => {
+      // If a session was created, end it.
+      if (testSession) {
+        await testSession.end().catch(() => {});
+      }
+    });
+
+    return navigator.xr.test.simulateDeviceConnection(fakeDeviceInit)
+        .then((controller) => {
+          testDeviceController = controller;
+          return sessionObjects.gl.makeXRCompatible();
+        })
+        .then(() => new Promise((resolve, reject) => {
+                // Perform the session request in a user gesture.
+                xr_debug(name, 'simulateUserActivation');
+                navigator.xr.test.simulateUserActivation(() => {
+                  xr_debug(name, 'document.hasFocus()=' + document.hasFocus());
+                  navigator.xr.requestSession(sessionMode, sessionInit || {})
+                      .then((session) => {
+                        xr_debug(name, 'session start');
+                        testSession = session;
+                        session.mode = sessionMode;
+                        let glLayer = new XRWebGLLayer(session, sessionObjects.gl, gllayerProperties);
+                        glLayer.context = sessionObjects.gl;
+                        // Session must have a baseLayer or frame requests
+                        // will be ignored.
+                        session.updateRenderState({
+                            baseLayer: glLayer
+                        });
+                        sessionObjects.glLayer = glLayer;
+                        xr_debug(name, 'session.visibilityState=' + session.visibilityState);
+                        resolve(func(session, testDeviceController, t, sessionObjects));
+                      })
+                      .catch((err) => {
+                        xr_debug(name, 'error: ' + err);
+                        reject(
+                            'Session with params ' +
+                            JSON.stringify(sessionMode) +
+                            ' was rejected on device ' +
+                            JSON.stringify(fakeDeviceInit) +
+                            ' with error: ' + err);
+                      });
+                });
+        }));
   }
-  let gl = webglCanvas.getContext('webgl', {alpha: false, antialias: false, ...glcontextProperties});
-  sessionObjects.gl = gl;
 
   xr_promise_test(
-      name,
-      (t) => {
-          // Ensure that any pending sessions are ended when done. This needs to
-          // use a cleanup function to ensure proper sequencing. If this were
-          // done in a .then() for the success case, a test that expected
-          // failure would already be marked done at the time that runs, and the
-          // shutdown would interfere with the next test which may have started.
-          t.add_cleanup(async () => {
-            // If a session was created, end it.
-            if (testSession) {
-              await testSession.end().catch(() => {});
-            }
-          });
-
-          return navigator.xr.test.simulateDeviceConnection(fakeDeviceInit)
-              .then((controller) => {
-                testDeviceController = controller;
-                return gl.makeXRCompatible();
-              })
-              .then(() => new Promise((resolve, reject) => {
-                      // Perform the session request in a user gesture.
-                      xr_debug(name, 'simulateUserActivation');
-                      navigator.xr.test.simulateUserActivation(() => {
-                        xr_debug(name, 'document.hasFocus()=' + document.hasFocus());
-                        navigator.xr.requestSession(sessionMode, sessionInit || {})
-                            .then((session) => {
-                              xr_debug(name, 'session start');
-                              testSession = session;
-                              session.mode = sessionMode;
-                              let glLayer = new XRWebGLLayer(session, gl, gllayerProperties);
-                              glLayer.context = gl;
-                              // Session must have a baseLayer or frame requests
-                              // will be ignored.
-                              session.updateRenderState({
-                                  baseLayer: glLayer
-                              });
-                              sessionObjects.glLayer = glLayer;
-                              xr_debug(name, 'session.visibilityState=' + session.visibilityState);
-                              resolve(func(session, testDeviceController, t, sessionObjects));
-                            })
-                            .catch((err) => {
-                              xr_debug(name, 'error: ' + err);
-                              reject(
-                                  'Session with params ' +
-                                  JSON.stringify(sessionMode) +
-                                  ' was rejected on device ' +
-                                  JSON.stringify(fakeDeviceInit) +
-                                  ' with error: ' + err);
-                            });
-                      });
-              }));
-      },
-      properties);
+    name + ' - webgl',
+    runTest,
+    properties,
+    'webgl',
+    {alpha: false, antialias: false, ...glcontextProperties}
+    );
+  xr_promise_test(
+    name + ' - webgl2',
+    runTest,
+    properties,
+    'webgl2',
+    {alpha: false, antialias: false, ...glcontextProperties});
 }
 
 
diff --git a/webxr/webGLCanvasContext_create_xrcompatible.https.html b/webxr/webGLCanvasContext_create_xrcompatible.https.html
index 2b3a1fc..e3e83a5 100644
--- a/webxr/webGLCanvasContext_create_xrcompatible.https.html
+++ b/webxr/webGLCanvasContext_create_xrcompatible.https.html
@@ -4,36 +4,49 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas id="webgl-canvas"></canvas>
   <script>
-    xr_promise_test("Creating a webglCanvasContext with no device",
-      (t) => {
-        let webglCanvas = document.createElement('canvas');
-        let gl = webglCanvas.getContext('webgl');
 
-        assert_false(gl.getContextAttributes().xrCompatible);
-        return promise_rejects_dom(t, "InvalidStateError", gl.makeXRCompatible());
+    function testNoDevice(t, gl) {
+      assert_false(gl.getContextAttributes().xrCompatible);
+      return promise_rejects_dom(t, "InvalidStateError", gl.makeXRCompatible());
+    }
+
+    xr_promise_test("Creating a webgl context with no device",
+      testNoDevice, null, 'webgl');
+
+    xr_promise_test("Creating a webgl2 context with no device",
+      testNoDevice, null, 'webgl2');
+
+    function testXrCompatible(t, gl) {
+      let offscreenGl = null;
+      let offscreenGl2 = null;
+      return navigator.xr.test.simulateDeviceConnection(TRACKED_IMMERSIVE_DEVICE)
+        .then( (controller) => {
+          return gl.makeXRCompatible();
+        }).then( () => {
+          assert_true(gl.getContextAttributes().xrCompatible);
+
+          // Check that an offscreen webgl context behaves no different.
+          let offscreenCanvas = document.createElement('canvas');
+          offscreenGl = offscreenCanvas.getContext('webgl');
+          return offscreenGl.makeXRCompatible();
+        }).then( () => {
+          assert_true(offscreenGl.getContextAttributes().xrCompatible);
+
+          // Check that an offscreen webgl2 context behaves no different.
+          let offscreenCanvas = document.createElement('canvas');
+          offscreenGl2 = offscreenCanvas.getContext('webgl2');
+          return offscreenGl2.makeXRCompatible();
+      }).then( () => {
+          assert_true(offscreenGl2.getContextAttributes().xrCompatible);
       });
+    }
 
-    xr_promise_test("An XR-compatible webglCanvasContext can be created",
-      (t) => {
-        let gl = null;
-        let offscreenGl = null;
-        return navigator.xr.test.simulateDeviceConnection(TRACKED_IMMERSIVE_DEVICE)
-          .then( (controller) => {
-            let webglCanvas = document.getElementById('webgl-canvas');
-            gl = webglCanvas.getContext('webgl');
-            return gl.makeXRCompatible();
-          }).then( () => {
-            assert_true(gl.getContextAttributes().xrCompatible);
+    xr_promise_test("An XR-compatible webgl context can be created",
+      testXrCompatible, null, 'webgl');
 
-            // Check that an offscreen context behaves no different.
-            let offscreenCanvas = document.createElement('canvas');
-            offscreenGl = offscreenCanvas.getContext('webgl');
-            return offscreenGl.makeXRCompatible();
-          }).then( () => {
-            assert_true(offscreenGl.getContextAttributes().xrCompatible);
-          });
-      });
+    xr_promise_test("An XR-compatible webgl2 context can be created",
+      testXrCompatible, null, 'webgl2');
+
   </script>
 </body>
diff --git a/webxr/webGLCanvasContext_makecompatible_contextlost.https.html b/webxr/webGLCanvasContext_makecompatible_contextlost.https.html
index 0e59807..354c614 100644
--- a/webxr/webGLCanvasContext_makecompatible_contextlost.https.html
+++ b/webxr/webGLCanvasContext_makecompatible_contextlost.https.html
@@ -4,22 +4,25 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas id="webgl-canvas"></canvas>
   <script>
 
-    xr_promise_test(
-      "A lost webglCanvasContext should not be able to set xr compatibility",
-     (t) => {
+    function testContextLost(t, gl) {
       return navigator.xr.test.simulateDeviceConnection(TRACKED_IMMERSIVE_DEVICE)
         .then( (controller) => {
-          webglCanvas = document.getElementById('webgl-canvas');
-          gl = webglCanvas.getContext('webgl');
           return gl.makeXRCompatible();
         }).then( () => {
           gl.getExtension('WEBGL_lose_context').loseContext();
           return promise_rejects_dom(t, 'InvalidStateError', gl.makeXRCompatible());
         });
-    });
+    }
+
+    xr_promise_test(
+      "A lost webgl context should not be able to set xr compatibility",
+      testContextLost, null, 'webgl');
+
+    xr_promise_test(
+      "A lost webgl2 context should not be able to set xr compatibility",
+      testContextLost, null, 'webgl2');
 
   </script>
 </body>
diff --git a/webxr/webGLCanvasContext_makecompatible_reentrant.https.html b/webxr/webGLCanvasContext_makecompatible_reentrant.https.html
index f412c6f..f54a878 100644
--- a/webxr/webGLCanvasContext_makecompatible_reentrant.https.html
+++ b/webxr/webGLCanvasContext_makecompatible_reentrant.https.html
@@ -5,11 +5,8 @@
 <script src="resources/webxr_util.js"></script>
 <script>
 
-xr_promise_test(
-  "Verify promise from a non-reentrant to makeXRCompatible() is resolved",
-  (t) => {
-    var gl = document.createElement('canvas').getContext('webgl');
-    return navigator.xr.test.simulateDeviceConnection(TRACKED_IMMERSIVE_DEVICE)
+function testNonReentrant(t, gl) {
+  return navigator.xr.test.simulateDeviceConnection(TRACKED_IMMERSIVE_DEVICE)
       .then((controller) => {
         assert_false(gl.getContextAttributes().xrCompatible);
         return gl.makeXRCompatible();
@@ -19,13 +16,17 @@
       }).then(() => {
         assert_true(gl.getContextAttributes().xrCompatible);
       });
-  });
+}
 
 xr_promise_test(
-  "Verify promises from reentrant calls to makeXRCompatible() are resolved",
-  (t) => {
-    var gl = document.createElement('canvas').getContext('webgl');
-    return navigator.xr.test.simulateDeviceConnection(TRACKED_IMMERSIVE_DEVICE)
+  "Verify promise from a non-reentrant call to makeXRCompatible() is resolved for webgl",
+  testNonReentrant, null, 'webgl');
+xr_promise_test(
+  "Verify promise from a non-reentrant call to makeXRCompatible() is resolved for webgl2",
+  testNonReentrant, null, 'webgl2');
+
+function testReentrant(t, gl) {
+  return navigator.xr.test.simulateDeviceConnection(TRACKED_IMMERSIVE_DEVICE)
       .then((controller) => {
         assert_false(gl.getContextAttributes().xrCompatible);
 
@@ -35,6 +36,13 @@
       }).then(() => {
         assert_true(gl.getContextAttributes().xrCompatible);
       });
-  });
+}
+
+xr_promise_test(
+  "Verify promises from reentrant calls to makeXRCompatible() are resolved for webgl",
+  testReentrant, null, 'webgl');
+xr_promise_test(
+  "Verify promises from reentrant calls to makeXRCompatible() are resolved for webgl2",
+  testReentrant, null, 'webgl2');
 
 </script>
diff --git a/webxr/xrBoundedReferenceSpace_updates.https.html b/webxr/xrBoundedReferenceSpace_updates.https.html
index bb4cb2c..c5f9b7f 100644
--- a/webxr/xrBoundedReferenceSpace_updates.https.html
+++ b/webxr/xrBoundedReferenceSpace_updates.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas></canvas>
 
 <script>
 let testName =
diff --git a/webxr/xrDevice_disconnect_ends.https.html b/webxr/xrDevice_disconnect_ends.https.html
index ace64e8..644a4d6 100644
--- a/webxr/xrDevice_disconnect_ends.https.html
+++ b/webxr/xrDevice_disconnect_ends.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
 
   <script>
     const testName = "Immersive session ends when device is disconnected";
diff --git a/webxr/xrDevice_requestSession_immersive.https.html b/webxr/xrDevice_requestSession_immersive.https.html
index be0bb32..6ff8821 100644
--- a/webxr/xrDevice_requestSession_immersive.https.html
+++ b/webxr/xrDevice_requestSession_immersive.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
   <script>
     xr_session_promise_test(
       "Tests requestSession resolves when supported",
diff --git a/webxr/xrDevice_requestSession_optionalFeatures.https.html b/webxr/xrDevice_requestSession_optionalFeatures.https.html
index 0071b81..f773762 100644
--- a/webxr/xrDevice_requestSession_optionalFeatures.https.html
+++ b/webxr/xrDevice_requestSession_optionalFeatures.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
   <script>
     xr_session_promise_test(
       "Tests requestSession accepts XRSessionInit dictionary",
diff --git a/webxr/xrFrame_getPose.https.html b/webxr/xrFrame_getPose.https.html
index 1f3e376..9cd7922 100644
--- a/webxr/xrFrame_getPose.https.html
+++ b/webxr/xrFrame_getPose.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas></canvas>
 
 <script>
 
diff --git a/webxr/xrFrame_getViewerPose_getPose.https.html b/webxr/xrFrame_getViewerPose_getPose.https.html
index 7d26983..05cbf78 100644
--- a/webxr/xrFrame_getViewerPose_getPose.https.html
+++ b/webxr/xrFrame_getViewerPose_getPose.https.html
@@ -5,7 +5,6 @@
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
   <script src="resources/webxr_test_asserts.js"></script>
-  <canvas></canvas>
 
   <script>
 
diff --git a/webxr/xrFrame_lifetime.https.html b/webxr/xrFrame_lifetime.https.html
index 7c71f0a..e457ef0 100644
--- a/webxr/xrFrame_lifetime.https.html
+++ b/webxr/xrFrame_lifetime.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
 
   <script>
     let immersiveTestName = "XRFrame methods throw exceptions outside of the " +
diff --git a/webxr/xrFrame_session_sameObject.https.html b/webxr/xrFrame_session_sameObject.https.html
index cbbef68..d1d4beb 100644
--- a/webxr/xrFrame_session_sameObject.https.html
+++ b/webxr/xrFrame_session_sameObject.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "XRFrame.session meets [SameObject] requirement";
diff --git a/webxr/xrInputSource_add_remove.https.html b/webxr/xrInputSource_add_remove.https.html
index 7764017..0025331 100644
--- a/webxr/xrInputSource_add_remove.https.html
+++ b/webxr/xrInputSource_add_remove.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 
diff --git a/webxr/xrInputSource_emulatedPosition.https.html b/webxr/xrInputSource_emulatedPosition.https.html
index 2bc21ff..8a4aec4 100644
--- a/webxr/xrInputSource_emulatedPosition.https.html
+++ b/webxr/xrInputSource_emulatedPosition.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 
diff --git a/webxr/xrInputSource_profiles.https.html b/webxr/xrInputSource_profiles.https.html
index f55e682..de70c90 100644
--- a/webxr/xrInputSource_profiles.https.html
+++ b/webxr/xrInputSource_profiles.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "WebXR InputSource's profiles list can be set";
diff --git a/webxr/xrInputSource_sameObject.https.html b/webxr/xrInputSource_sameObject.https.html
index 305e5f9..999b4d8 100644
--- a/webxr/xrInputSource_sameObject.https.html
+++ b/webxr/xrInputSource_sameObject.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "XRInputSource attributes meet [SameObject] requirement";
diff --git a/webxr/xrPose_transform_sameObject.https.html b/webxr/xrPose_transform_sameObject.https.html
index 8e2239c..9ea07fc 100644
--- a/webxr/xrPose_transform_sameObject.https.html
+++ b/webxr/xrPose_transform_sameObject.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "XRPose.transform meets [SameObject] requirement";
diff --git a/webxr/xrReferenceSpace_originOffset.https.html b/webxr/xrReferenceSpace_originOffset.https.html
index f6929f2..d93f696 100644
--- a/webxr/xrReferenceSpace_originOffset.https.html
+++ b/webxr/xrReferenceSpace_originOffset.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "Updating XRReferenceSpace origin offset updates view and input matrices.";
diff --git a/webxr/xrReferenceSpace_originOffsetBounded.https.html b/webxr/xrReferenceSpace_originOffsetBounded.https.html
index 7ce4aca..e037353 100644
--- a/webxr/xrReferenceSpace_originOffsetBounded.https.html
+++ b/webxr/xrReferenceSpace_originOffsetBounded.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 
diff --git a/webxr/xrReferenceSpace_originOffset_viewer.https.html b/webxr/xrReferenceSpace_originOffset_viewer.https.html
index 5cd0f02..8a9fb34 100644
--- a/webxr/xrReferenceSpace_originOffset_viewer.https.html
+++ b/webxr/xrReferenceSpace_originOffset_viewer.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "Creating XRReferenceSpace origin offset off of `viewer` space works.";
diff --git a/webxr/xrReferenceSpace_relationships.https.html b/webxr/xrReferenceSpace_relationships.https.html
index f97ca66..5b680fb 100644
--- a/webxr/xrReferenceSpace_relationships.https.html
+++ b/webxr/xrReferenceSpace_relationships.https.html
@@ -5,7 +5,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas></canvas>
 <script>
 let testName =
   "Bounded space, viewer space, local and local-floor space have correct poses w.r.t. each other";
diff --git a/webxr/xrRigidTransform_constructor.https.html b/webxr/xrRigidTransform_constructor.https.html
index 5e055ef..fbea1c1 100644
--- a/webxr/xrRigidTransform_constructor.https.html
+++ b/webxr/xrRigidTransform_constructor.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 <script>
 
 let testName = "XRRigidTransform constructor works";
diff --git a/webxr/xrRigidTransform_inverse.https.html b/webxr/xrRigidTransform_inverse.https.html
index 79acca9..cd5b345 100644
--- a/webxr/xrRigidTransform_inverse.https.html
+++ b/webxr/xrRigidTransform_inverse.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas id="webgl-canvas"></canvas>
 <script>
 
 let testName = "XRRigidTransform inverse works";
diff --git a/webxr/xrRigidTransform_sameObject.https.html b/webxr/xrRigidTransform_sameObject.https.html
index 57c7ef1..8ff4f5c 100644
--- a/webxr/xrRigidTransform_sameObject.https.html
+++ b/webxr/xrRigidTransform_sameObject.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 <script>
 
 let testName = "XRRigidTransform position and orientation meet [SameObject] requirements";
diff --git a/webxr/xrSession_cancelAnimationFrame.https.html b/webxr/xrSession_cancelAnimationFrame.https.html
index 6a294f2..2b3403f 100644
--- a/webxr/xrSession_cancelAnimationFrame.https.html
+++ b/webxr/xrSession_cancelAnimationFrame.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
 
   <script>
     let immersiveTestName = "XRSession requestAnimationFrame callbacks can be "
diff --git a/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html b/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html
index 51a639b..f036e30 100644
--- a/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html
+++ b/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
   <script>
     let immersiveTestName = "XRSession cancelAnimationFrame does not have unexpected "
       + "behavior when given invalid handles on immersive testSession";
diff --git a/webxr/xrSession_end.https.html b/webxr/xrSession_end.https.html
index e8c078e..dccc550 100644
--- a/webxr/xrSession_end.https.html
+++ b/webxr/xrSession_end.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
 
   <script>
     const immersivetestName = "end event fires when immersive session ends";
diff --git a/webxr/xrSession_input_events_end.https.html b/webxr/xrSession_input_events_end.https.html
index 636562d..b7f6461 100644
--- a/webxr/xrSession_input_events_end.https.html
+++ b/webxr/xrSession_input_events_end.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "Calling end during an input callback stops processing at the right time";
diff --git a/webxr/xrSession_requestAnimationFrame_callback_calls.https.html b/webxr/xrSession_requestAnimationFrame_callback_calls.https.html
index 98231c8..ee29b87 100644
--- a/webxr/xrSession_requestAnimationFrame_callback_calls.https.html
+++ b/webxr/xrSession_requestAnimationFrame_callback_calls.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
 
   <script>
     let immersiveTestName = "XRSession requestAnimationFrame calls the " +
diff --git a/webxr/xrSession_requestAnimationFrame_data_valid.https.html b/webxr/xrSession_requestAnimationFrame_data_valid.https.html
index 760ff3d..812c79c 100644
--- a/webxr/xrSession_requestAnimationFrame_data_valid.https.html
+++ b/webxr/xrSession_requestAnimationFrame_data_valid.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
 
   <script>
     const testName = "RequestAnimationFrame resolves with good data";
diff --git a/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html b/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html
index 1b54f5f..68ad344 100644
--- a/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html
+++ b/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html
@@ -5,7 +5,6 @@
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
   <script src="resources/webxr_test_asserts.js"></script>
-  <canvas></canvas>
 
   <script>
 
diff --git a/webxr/xrSession_requestAnimationFrame_timestamp.https.html b/webxr/xrSession_requestAnimationFrame_timestamp.https.html
index 3263889..ee6bb49 100644
--- a/webxr/xrSession_requestAnimationFrame_timestamp.https.html
+++ b/webxr/xrSession_requestAnimationFrame_timestamp.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 const TEN_SECONDS = 10000; // 10k ms in ten seconds
diff --git a/webxr/xrSession_requestReferenceSpace.https.html b/webxr/xrSession_requestReferenceSpace.https.html
index b141d6d..b8765fd 100644
--- a/webxr/xrSession_requestReferenceSpace.https.html
+++ b/webxr/xrSession_requestReferenceSpace.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
   <script>
 
     let immersiveTestName =
diff --git a/webxr/xrSession_requestReferenceSpace_features.https.html b/webxr/xrSession_requestReferenceSpace_features.https.html
index bdfd8c7..a20223f 100644
--- a/webxr/xrSession_requestReferenceSpace_features.https.html
+++ b/webxr/xrSession_requestReferenceSpace_features.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
   <script>
 
     let makeSpaceTest = (space_type) => {
diff --git a/webxr/xrSession_requestSessionDuringEnd.https.html b/webxr/xrSession_requestSessionDuringEnd.https.html
index 2ab6cb7..38133b6 100644
--- a/webxr/xrSession_requestSessionDuringEnd.https.html
+++ b/webxr/xrSession_requestSessionDuringEnd.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
 
   <script>
     function testFunctionGenerator(createSessionFromEventCallback) {
diff --git a/webxr/xrSession_sameObject.https.html b/webxr/xrSession_sameObject.https.html
index 66aeef8..1795ee7 100644
--- a/webxr/xrSession_sameObject.https.html
+++ b/webxr/xrSession_sameObject.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "XRSession attributes meet [SameObject] requirement";
diff --git a/webxr/xrSession_viewer_referenceSpace.https.html b/webxr/xrSession_viewer_referenceSpace.https.html
index fd6082b..0098d4d 100644
--- a/webxr/xrSession_viewer_referenceSpace.https.html
+++ b/webxr/xrSession_viewer_referenceSpace.https.html
@@ -4,7 +4,6 @@
   <script src=/resources/testharnessreport.js></script>
   <script src="resources/webxr_util.js"></script>
   <script src="resources/webxr_test_constants.js"></script>
-  <canvas></canvas>
 
   <script>
 
diff --git a/webxr/xrSession_visibilityState.https.html b/webxr/xrSession_visibilityState.https.html
index 2311792..12655f4 100644
--- a/webxr/xrSession_visibilityState.https.html
+++ b/webxr/xrSession_visibilityState.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "Ensures that the XRSession's visibilityState is correctly "
diff --git a/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html b/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html
index 96729160..f1e907d 100644
--- a/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html
+++ b/webxr/xrStationaryReferenceSpace_floorlevel_updates.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas></canvas>
 
 <script>
 let immersiveTestName = "'floor-level' XRStationaryReferenceSpace updates properly when " +
diff --git a/webxr/xrView_eyes.https.html b/webxr/xrView_eyes.https.html
index 956edba..ac017cd 100644
--- a/webxr/xrView_eyes.https.html
+++ b/webxr/xrView_eyes.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas></canvas>
 
 <script>
 
diff --git a/webxr/xrView_match.https.html b/webxr/xrView_match.https.html
index 4bb4882..2ef4307 100644
--- a/webxr/xrView_match.https.html
+++ b/webxr/xrView_match.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/xrView_oneframeupdate.https.html b/webxr/xrView_oneframeupdate.https.html
index 6671721..6c50f6f 100644
--- a/webxr/xrView_oneframeupdate.https.html
+++ b/webxr/xrView_oneframeupdate.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/xrView_sameObject.https.html b/webxr/xrView_sameObject.https.html
index 1213bcb..2defa72 100644
--- a/webxr/xrView_sameObject.https.html
+++ b/webxr/xrView_sameObject.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "XRView attributes meet [SameObject] requirement";
diff --git a/webxr/xrViewerPose_views_sameObject.https.html b/webxr/xrViewerPose_views_sameObject.https.html
index ec1ee69..af64111 100644
--- a/webxr/xrViewerPose_views_sameObject.https.html
+++ b/webxr/xrViewerPose_views_sameObject.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas id="webgl-canvas"></canvas>
 
 <script>
 let testName = "XRViewerPose.views meets [SameObject] requirement";
diff --git a/webxr/xrViewport_valid.https.html b/webxr/xrViewport_valid.https.html
index 1b7d982..4588a3f 100644
--- a/webxr/xrViewport_valid.https.html
+++ b/webxr/xrViewport_valid.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 let testName = "XRViewport attributes are valid";
diff --git a/webxr/xrWebGLLayer_constructor.https.html b/webxr/xrWebGLLayer_constructor.https.html
index e5b2335..5796e1e 100644
--- a/webxr/xrWebGLLayer_constructor.https.html
+++ b/webxr/xrWebGLLayer_constructor.https.html
@@ -3,18 +3,10 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
-xr_promise_test("Ensure that XRWebGLLayer's constructor throws appropriate errors",
-  (t) => {
-  let webglCanvas = document.getElementsByTagName('canvas')[0];
-  let glAttributes = {
-    alpha: false,
-    antialias: false,
-    xrCompatible: false,
-  };
-  let gl = webglCanvas.getContext('webgl', glAttributes);
+
+function testConstructor(t, gl) {
   return navigator.xr.test.simulateDeviceConnection(TRACKED_IMMERSIVE_DEVICE)
     .then(() => {
       return navigator.xr.requestSession('inline')
@@ -52,7 +44,7 @@
 
             let lose_context_ext = gl.getExtension('WEBGL_lose_context');
 
-            webglCanvas.addEventListener('webglcontextlost', (ev) => {
+            gl.canvas.addEventListener('webglcontextlost', (ev) => {
               ev.preventDefault();
 
               try {
@@ -64,7 +56,7 @@
               }
             });
 
-            webglCanvas.addEventListener('webglcontextrestored', (ev) => {
+            gl.canvas.addEventListener('webglcontextrestored', (ev) => {
               resolve(xrSession.end().then(() => {
                 try {
                   let webglLayerBadSession = new XRWebGLLayer(xrSession, gl);
@@ -80,6 +72,11 @@
         });
       });
     });
-});
+}
+xr_promise_test("Ensure that XRWebGLLayer's constructor throws appropriate errors using webgl",
+  testConstructor, null, 'webgl');
+
+xr_promise_test("Ensure that XRWebGLLayer's constructor throws appropriate errors using webgl2",
+  testConstructor, null, 'webgl2');
 
 </script>
diff --git a/webxr/xrWebGLLayer_framebuffer_draw.https.html b/webxr/xrWebGLLayer_framebuffer_draw.https.html
index dd40865..eb797cf 100644
--- a/webxr/xrWebGLLayer_framebuffer_draw.https.html
+++ b/webxr/xrWebGLLayer_framebuffer_draw.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/xrWebGLLayer_framebuffer_sameObject.https.html b/webxr/xrWebGLLayer_framebuffer_sameObject.https.html
index b0f6378..75efc62 100644
--- a/webxr/xrWebGLLayer_framebuffer_sameObject.https.html
+++ b/webxr/xrWebGLLayer_framebuffer_sameObject.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/xrWebGLLayer_framebuffer_scale.https.html b/webxr/xrWebGLLayer_framebuffer_scale.https.html
index 3faab3b..065fc3d 100644
--- a/webxr/xrWebGLLayer_framebuffer_scale.https.html
+++ b/webxr/xrWebGLLayer_framebuffer_scale.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 
diff --git a/webxr/xrWebGLLayer_opaque_framebuffer.https.html b/webxr/xrWebGLLayer_opaque_framebuffer.https.html
index 4d27a91..f0d63de 100644
--- a/webxr/xrWebGLLayer_opaque_framebuffer.https.html
+++ b/webxr/xrWebGLLayer_opaque_framebuffer.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 let immersiveTestName = "Ensure that the framebuffer given by the WebGL layer" +
@@ -49,25 +48,29 @@
   assert_equals(xrFramebuffer, boundFramebuffer);
   assert_equals(gl.getError(), gl.NO_ERROR);
 
-  // Ensure the framebuffer attachment properties cannot be inspected.
-  let attachments = [
-    gl.COLOR_ATTACHMENT0,
-    gl.DEPTH_ATTACHMENT,
-    gl.STENCIL_ATTACHMENT,
-  ];
+  // WebGL 2 does not throw an error and instead returns 0 when there are no
+  // attachments
+  if (gl.getParameter(gl.VERSION).includes("WebGL 1.0")) {
+    // Ensure the framebuffer attachment properties cannot be inspected.
+    let attachments = [
+      gl.COLOR_ATTACHMENT0,
+      gl.DEPTH_ATTACHMENT,
+      gl.STENCIL_ATTACHMENT,
+    ];
 
-  let parameters = [
-    gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
-    gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
-    gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
-    gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
-  ];
+    let parameters = [
+      gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
+      gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
+      gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
+      gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
+    ];
 
-  for (let attachment of attachments) {
-    for (let parameter of parameters) {
-      let value = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment, parameter);
-      assert_equals(value, null);
-      assert_equals(gl.getError(), gl.INVALID_OPERATION);
+    for (let attachment of attachments) {
+      for (let parameter of parameters) {
+        let value = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment, parameter);
+        assert_equals(value, null);
+        assert_equals(gl.getError(), gl.INVALID_OPERATION);
+      }
     }
   }
 
diff --git a/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html b/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html
index 8e3e60c..7eadd00 100644
--- a/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html
+++ b/webxr/xrWebGLLayer_opaque_framebuffer_stencil.https.html
@@ -3,7 +3,6 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_constants.js"></script>
-<canvas />
 
 <script>
 let immersiveTestName = "Ensure that the framebuffer given by the WebGL layer" +
@@ -43,7 +42,7 @@
   const gl = sessionObjects.gl;
   const webglLayer = sessionObjects.glLayer;
   const xrFramebuffer = webglLayer.framebuffer;
-  const webglCanvas = document.getElementsByTagName('canvas')[0];
+  const webglCanvas = sessionObjects.gl.canvas;
 
   session.requestAnimationFrame((time, xrFrame) => {
     t.step(() => {
diff --git a/webxr/xrWebGLLayer_viewports.https.html b/webxr/xrWebGLLayer_viewports.https.html
index 94a23dc..74cc86f 100644
--- a/webxr/xrWebGLLayer_viewports.https.html
+++ b/webxr/xrWebGLLayer_viewports.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas></canvas>
 
 <script>
 
diff --git a/webxr/xr_viewport_scale.https.html b/webxr/xr_viewport_scale.https.html
index baff125..86e6f40 100644
--- a/webxr/xr_viewport_scale.https.html
+++ b/webxr/xr_viewport_scale.https.html
@@ -4,7 +4,6 @@
 <script src="resources/webxr_test_constants.js"></script>
 <script src="resources/webxr_util.js"></script>
 <script src="resources/webxr_test_asserts.js"></script>
-<canvas></canvas>
 
 <script>