xr_viewport_scale.https.html (8416B)
1 <!DOCTYPE html> 2 <script src="/resources/testharness.js"></script> 3 <script src="/resources/testharnessreport.js"></script> 4 <script src="resources/webxr_test_constants.js"></script> 5 <script src="resources/webxr_util.js"></script> 6 <script src="resources/webxr_test_asserts.js"></script> 7 8 <script> 9 10 let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; 11 12 let isValidViewport = function(viewport) { 13 // Ensure the returned object is an XRViewport object 14 assert_not_equals(viewport, null); 15 assert_true(viewport instanceof XRViewport); 16 17 // Ensure the viewport dimensions are valid 18 assert_greater_than_equal(viewport.x, 0); 19 assert_greater_than_equal(viewport.y, 0); 20 assert_greater_than_equal(viewport.width, 1); 21 assert_greater_than_equal(viewport.height, 1); 22 }; 23 24 let containsViewport = function(outer, inner) { 25 assert_less_than_equal(inner.x, outer.x); 26 assert_less_than_equal(inner.y, outer.y); 27 assert_less_than_equal(inner.x + inner.width, outer.x + outer.width); 28 assert_less_than_equal(inner.y + inner.height, outer.y + outer.height); 29 }; 30 31 let isSameViewport = function(a, b) { 32 return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height; 33 }; 34 35 let assertSameViewport = function(a, b) { 36 assert_equals(a.x, b.x, "viewport x should match"); 37 assert_equals(a.y, b.y, "viewport y should match"); 38 assert_equals(a.width, b.width, "viewport width should match"); 39 assert_equals(a.height, b.height, "viewport height should match"); 40 }; 41 42 let testFunction = function(name, firstScale, nextFrame, session, fakeDeviceController, t) { 43 return session.requestReferenceSpace('viewer') 44 .then((space) => new Promise((resolve) => { 45 function onFrame(time, xrFrame1) { 46 let debug = xr_debug.bind(this, name); 47 debug('first frame'); 48 let layer = xrFrame1.session.renderState.baseLayer; 49 50 let fullViewports = []; 51 52 let views1 = xrFrame1.getViewerPose(space).views; 53 54 for (view of views1) { 55 let viewport1a = layer.getViewport(view); 56 t.step(() => isValidViewport(viewport1a)); 57 fullViewports.push(viewport1a); 58 } 59 60 // Now request a changed viewport scale. This must not change the 61 // viewports within this frame since they were already queried. 62 // If the UA supports viewport scaling, the change applies on the 63 // next frame. If it doesn't support viewport scaling, this call 64 // has no effect. 65 for (view of views1) { 66 view.requestViewportScale(firstScale); 67 } 68 69 t.step(() => { 70 for (let i = 0; i < views1.length; ++i) { 71 let viewport1b = layer.getViewport(views1[i]); 72 assertSameViewport(viewport1b, fullViewports[i]); 73 } 74 }); 75 76 if (nextFrame) { 77 session.requestAnimationFrame((time, xrFrame2) => 78 nextFrame(name, t, session, space, layer, fullViewports, xrFrame2, resolve)); 79 } else { 80 // test is done 81 resolve(); 82 } 83 } 84 85 session.requestAnimationFrame(onFrame); 86 })); 87 }; 88 89 let testViewportValid = function(name, t, session, space, layer, fullViewports, xrFrame, resolve) { 90 let debug = xr_debug.bind(this, name); 91 debug('second frame'); 92 let views = xrFrame.getViewerPose(space).views; 93 for (let i = 0; i < views.length; ++i) { 94 let viewport = layer.getViewport(views[i]); 95 t.step(() => isValidViewport(viewport)); 96 t.step(() => containsViewport(fullViewports[i], viewport)); 97 } 98 resolve(); 99 }; 100 101 let testScaleAppliedNextFrame = function(name, t, session, space, layer, fullViewports, xrFrame, resolve) { 102 let debug = xr_debug.bind(this, name); 103 debug('second frame'); 104 let supportsScaling = false; 105 let views = xrFrame.getViewerPose(space).views; 106 for (let i = 0; i < views.length; ++i) { 107 let viewport = layer.getViewport(views[i]); 108 t.step(() => isValidViewport(viewport)); 109 t.step(() => containsViewport(fullViewports[i], viewport)); 110 if (!isSameViewport(fullViewports[i], viewport)) { 111 supportsScaling = true; 112 } 113 } 114 debug("supportsScaling=" + supportsScaling); 115 t.step(() => { 116 assert_implements_optional(supportsScaling, "requestViewportScale has no effect"); 117 }); 118 resolve(); 119 }; 120 121 let testScaleSameFrame = function(name, t, session, space, layer, fullViewports, xrFrame, resolve) { 122 let debug = xr_debug.bind(this, name); 123 debug('second frame'); 124 let supportsScaling = false; 125 let views = xrFrame.getViewerPose(space).views; 126 let viewports2 = []; 127 for (let i = 0; i < views.length; ++i) { 128 let viewport2 = layer.getViewport(views[i]); 129 viewports2.push(viewport2); 130 if (!isSameViewport(fullViewports[i], viewport2)) { 131 supportsScaling = true; 132 } 133 } 134 debug("supportsScaling=" + supportsScaling); 135 if (!supportsScaling) { 136 // End the test early. 137 t.step(() => { 138 assert_implements_optional(false, "requestViewportScale has no effect"); 139 resolve(); 140 }); 141 } 142 143 session.requestAnimationFrame((time, xrFrame3) => { 144 let views3 = xrFrame3.getViewerPose(space).views; 145 // Apply a new viewport scale before requesting viewports, 146 // this should take effect on the same frame. 147 for (view of views3) { 148 view.requestViewportScale(0.75); 149 } 150 for (let i = 0; i < views3.length; ++i) { 151 let viewport3 = layer.getViewport(views3[i]); 152 t.step(() => isValidViewport(viewport3)); 153 t.step(() => containsViewport(fullViewports[i], viewport3)); 154 t.step(() => containsViewport(viewport3, viewports2[i])); 155 t.step(() => { 156 // We don't know the exact expected size, but it should be in 157 // between the half-size and full-size viewports. 158 assert_false(isSameViewport(viewports2[i], viewport3)); 159 assert_false(isSameViewport(fullViewports[i], viewport3)); 160 }); 161 } 162 resolve(); 163 }); 164 }; 165 166 let testRecommendedScale = function(name, t, session, space, layer, fullViewports, xrFrame, resolve) { 167 let debug = xr_debug.bind(this, name); 168 debug('second frame'); 169 let views = xrFrame.getViewerPose(space).views; 170 let haveRecommendedScale = false; 171 for (view of views) { 172 let recommended = view.recommendedViewportScale; 173 view.requestViewportScale(recommended); 174 if (recommended !== null && recommended !== undefined) { 175 haveRecommendedScale = true; 176 t.step(() => { 177 assert_greater_than(recommended, 0.0, "recommended scale invalid"); 178 assert_less_than_equal(recommended, 1.0, "recommended scale invalid"); 179 }); 180 } 181 } 182 t.step(() => { 183 assert_implements_optional(haveRecommendedScale, "recommendedViewportScale not provided"); 184 }); 185 for (let i = 0; i < views.length; ++i) { 186 let viewport = layer.getViewport(views[i]); 187 t.step(() => isValidViewport(viewport)); 188 t.step(() => containsViewport(fullViewports[i], viewport)); 189 } 190 resolve(); 191 }; 192 193 for (let mode of ['inline', 'immersive-vr']) { 194 xr_session_promise_test( 195 "requestViewportScale valid viewport for " + mode + " session", 196 testFunction.bind(this, "valid viewport (0.5) " + mode, 0.5, testViewportValid), 197 fakeDeviceInitParams, 198 mode); 199 xr_session_promise_test( 200 "requestViewportScale valid viewport w/ null scale for " + mode + " session", 201 testFunction.bind(this, "valid viewport (null) " + mode, null, testViewportValid), 202 fakeDeviceInitParams, 203 mode); 204 xr_session_promise_test( 205 "requestViewportScale valid viewport w/ undefined scale for " + mode + " session", 206 testFunction.bind(this, "valid viewport (undefined) " + mode, null, testViewportValid), 207 fakeDeviceInitParams, 208 mode); 209 xr_session_promise_test( 210 "requestViewportScale valid viewport w/ very small scale for " + mode + " session", 211 testFunction.bind(this, "valid viewport (tiny) " + mode, 1e-6, testViewportValid), 212 fakeDeviceInitParams, 213 mode); 214 xr_session_promise_test( 215 "requestViewportScale applied next frame for " + mode + " session", 216 testFunction.bind(this, "scale applied next frame " + mode, 0.5, testScaleAppliedNextFrame), 217 fakeDeviceInitParams, 218 mode); 219 xr_session_promise_test( 220 "requestViewportScale same frame for " + mode + " session", 221 testFunction.bind(this, "same frame " + mode, 0.5, testScaleSameFrame), 222 fakeDeviceInitParams, 223 mode); 224 xr_session_promise_test( 225 "recommendedViewportScale for " + mode + " session", 226 testFunction.bind(this, "recommendedViewportScale " + mode, 0.5, testRecommendedScale), 227 fakeDeviceInitParams, 228 mode); 229 } 230 231 </script>