Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance2 / extensions / ovr_multiview2.html
blobba74d1398b315788ce8abe6e802bdd6a1a477f2f
1 <!--
2 Copyright (c) 2019 The Khronos Group Inc.
3 Use of this source code is governed by an MIT-style license that can be
4 found in the LICENSE.txt file.
5 -->
7 <!DOCTYPE html>
8 <html>
9 <head>
10 <meta charset="utf-8">
11 <title>WebGL OVR_multiview2 Conformance Tests</title>
12 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
13 <script src="../../js/js-test-pre.js"></script>
14 <script src="../../js/webgl-test-utils.js"></script>
15 <script src="../../js/tests/ovr_multiview2_util.js"></script>
16 <script id="requireDefine_GL_OVR_multiview2" type="x-shader/x-fragment">#version 300 es
17 #ifndef GL_OVR_multiview2
18 #error no GL_OVR_multiview2
19 #endif
20 precision highp float;
21 out vec4 my_FragColor;
22 void main() {
23 my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
25 </script>
26 <script id="forbidDefine_GL_OVR_multiview" type="x-shader/x-fragment">#version 300 es
27 #ifdef GL_OVR_multiview
28 #error legacy GL_OVR_multiview support must be forbidden
29 #endif
30 precision highp float;
31 out vec4 my_FragColor;
32 void main() {
33 my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
35 </script>
36 <script id="legacyMultiview1Shader" type="x-shader/x-fragment">#version 300 es
37 #extension GL_OVR_multiview: require
38 precision highp float;
39 out vec4 my_FragColor;
40 void main() {
41 my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
43 </script>
44 </head>
45 <body>
46 <div id="description"></div>
47 <div id="console"></div>
48 <script>
49 "use strict";
51 let wtu = WebGLTestUtils;
52 let gl = wtu.create3DContext(null, null, 2);
53 let ext = null;
55 function runExtensionDisabledTest()
57 debug("");
58 debug("Testing queries with extension disabled");
60 let maxViews = gl.getParameter(0x9631);
61 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query MAX_VIEWS_OVR without enabling OVR_multiview2");
63 let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9630);
64 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR without enabling OVR_multiview2");
65 let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9632);
66 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR without enabling OVR_multiview2");
69 function runQueryTest()
71 debug("");
72 debug("Testing querying MAX_VIEWS_OVR");
74 let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
75 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from querying MAX_VIEWS_OVR");
76 if (typeof maxViews != 'number') {
77 testFailed("Type of the value of MAX_VIEWS_OVR should be number, was " + (typeof maxViews));
79 if (maxViews < 2) {
80 testFailed("Value of MAX_VIEWS_OVR should be at least two, was: " + maxViews);
84 function runDefaultFramebufferQueryTest()
86 debug("");
87 debug("Testing querying base view index and num views on the default framebuffer");
88 gl.bindFramebuffer(gl.FRAMEBUFFER, null);
89 // Same behavior as FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
90 gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
91 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR is INVALID_ENUM for default framebuffer");
92 gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
93 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR is INVALID_ENUM for default framebuffer");
96 function runInvalidTextureTypeTest()
98 debug("");
99 debug("Testing invalid texture types");
100 let tex2D = createTextureWithNearestFiltering(gl.TEXTURE_2D);
101 gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 128, 128);
102 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2D, 0, 0, 1);
103 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 2D texture");
105 let texCube = createTextureWithNearestFiltering(gl.TEXTURE_CUBE_MAP);
106 gl.texStorage2D(gl.TEXTURE_CUBE_MAP, 1, gl.RGBA8, 128, 128);
107 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texCube, 0, 0, 1);
108 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a cube map texture");
110 let tex3D = createTextureWithNearestFiltering(gl.TEXTURE_3D);
111 gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, 128, 128, 2);
112 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, 0, 2);
113 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 3D texture");
117 * If allocateStorage is true, the test will allocate texture storage. If it is false, attachments are done without allocations.
119 function runFramebufferQueryTest(allocateStorage)
121 debug("");
122 debug("Testing querying attachment object type, baseViewIndex, numViews and framebuffer status. Texture storage is " + (allocateStorage ? "allocated" : "not allocated") + ".");
124 let checkQueryResult = function(actual, expected, name) {
125 if (actual != expected) {
126 testFailed('Unexpected ' + name + ': ' + actual + ' when it was set to ' + expected);
127 } else {
128 testPassed(name + ' was ' + actual + ' when queried from the framebuffer');
132 let setupAndQuery = function(colorTex, levelSet, baseViewIndexSet, numViewsSet) {
133 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, levelSet, baseViewIndexSet, numViewsSet);
134 let objectType = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
135 if (objectType != gl.TEXTURE) {
136 testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ', should be TEXTURE');
137 } else {
138 testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was TEXTURE');
141 let level = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL);
142 checkQueryResult(level, levelSet, "level");
144 let textureName = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
145 checkQueryResult(textureName, colorTex, "texture object");
147 let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
148 checkQueryResult(baseViewIndex, baseViewIndexSet, "baseViewIndex");
150 let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
151 checkQueryResult(numViews, numViewsSet, "numViews");
153 let layer = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
154 checkQueryResult(layer, baseViewIndexSet, "texture layer (should match baseViewIndex)");
157 let setupSecondAttachmentAndQueryStatus = function(colorTex2, baseViewIndex, numViews, expectedStatus, msg) {
158 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, colorTex2, 0, baseViewIndex, numViews);
159 let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
160 if (status != expectedStatus) {
161 testFailed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' did not match with the expected value: ' + wtu.glEnumToString(gl, expectedStatus) + ' - ' + msg);
162 } else {
163 testPassed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' matched with the expected value - ' + msg);
167 let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
169 let fb = gl.createFramebuffer();
170 gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
171 let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR);
172 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying baseViewIndex from a nonexistent attachment");
173 if (baseViewIndex != null) {
174 testFailed('Unexpected baseViewIndex ' + baseViewIndex + ' on a framebuffer without attachments');
175 } else {
176 testPassed('Querying baseViewIndex returned null on a framebuffer without attachments');
178 let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR);
179 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying numViews from a nonexistent attachment");
180 if (numViews != null) {
181 testFailed('Unexpected numViews ' + numViews + ' on a framebuffer without attachments');
182 } else {
183 testPassed('Querying numViews returned null on a framebuffer without attachments');
186 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
187 if (allocateStorage) {
188 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 2, gl.RGBA8, 128, 128, maxViews);
190 setupAndQuery(colorTex, 0, 0, maxViews);
191 setupAndQuery(colorTex, 1, 0, 2);
192 setupAndQuery(colorTex, 0, 1, maxViews - 1);
194 // Test matching and mismatching attachments for framebuffer status.
195 let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
196 if (allocateStorage) {
197 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, 128, 128, maxViews);
199 setupSecondAttachmentAndQueryStatus(colorTex2, 1, maxViews - 1, allocateStorage ? gl.FRAMEBUFFER_COMPLETE : gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 'matching baseViewIndex and numViews on different attachments');
200 if (allocateStorage) {
201 setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'baseViewIndex mismatch');
202 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
203 setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'numViews mismatch');
206 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from framebuffer queries");
209 function runInvalidViewsTest()
211 debug("");
212 debug("Testing invalid out-of-range values for baseViewIndex and numViews");
214 let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
215 let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS);
217 let fb = gl.createFramebuffer();
218 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
219 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
220 // Don't allocate storage since it's not needed for the validation.
221 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews + 1);
222 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified too many views");
223 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 0);
224 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified zero views");
225 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, -1, 2);
226 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified negative baseViewIndex");
228 let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
229 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews + 1, maxViews);
230 // baseViewIndex + numViews = (maxLayers - maxViews + 1) + maxViews = maxLayers + 1
231 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified so many views that baseViewIndex + numViews is greater than MAX_ARRAY_TEXTURE_LAYERS");
232 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews, maxViews);
233 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex + numViews is exactly MAX_ARRAY_TEXTURE_LAYERS");
236 function runDetachTest()
238 debug("");
239 debug("Testing detaching multiview attachments");
241 let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR);
242 let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS);
244 let fb = gl.createFramebuffer();
245 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
246 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
247 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
248 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, null, 0, maxLayers + 1, 0);
249 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex and numViews are not validated when detaching");
250 let objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
251 if (objectType != gl.NONE) {
252 testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE');
253 } else {
254 testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
257 ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews);
258 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
259 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Can detach with framebufferTexture2D as well.");
260 objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
261 if (objectType != gl.NONE) {
262 testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE');
263 } else {
264 testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach');
268 function runShaderCompileTest(extensionEnabled)
270 debug("");
271 debug("Testing shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled"));
273 let prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "requireDefine_GL_OVR_multiview2"], undefined, undefined, true);
274 expectTrue(!extensionEnabled == !prog,
275 "GL_OVR_multiview2 must be defined by the preprocessor iff OVR_multiview2 is enabled by getExtension.");
276 if (extensionEnabled) {
277 prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "forbidDefine_GL_OVR_multiview"], undefined, undefined, true);
278 expectTrue(prog, "GL_OVR_multiview must never be defined by the preprocessor.");
280 prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "legacyMultiview1Shader"], undefined, undefined, true);
281 expectTrue(!prog, "#extension GL_OVR_multiview must be forbidden.");
284 if (!extensionEnabled) {
285 let multiviewShaders = [
286 getMultiviewPassthroughVertexShader(2),
287 getMultiviewColorFragmentShader()
289 let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
290 if (testProgram) {
291 testFailed("Compilation of shaders using extension functionality succeeded when the extension is disabled, should fail.");
292 } else {
293 testPassed("Compilation of shaders using extension functionality should fail when the extension is disabled.");
298 function runClearTest()
300 debug("");
301 debug("Testing that calling clear() clears all views");
303 let width = 256;
304 let height = 256;
306 let views = gl.getParameter(ext.MAX_VIEWS_OVR);
308 let fb = gl.createFramebuffer();
309 gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
310 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
311 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
312 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
314 gl.viewport(0, 0, width, height);
316 gl.clearColor(0, 1, 1, 1);
317 gl.clear(gl.COLOR_BUFFER_BIT);
318 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear");
320 let readFb = gl.createFramebuffer();
321 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
322 for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
323 gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
324 let expectedColor = [0, 255, 255, 255];
325 wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be cyan');
329 function runFragmentShaderRenderTest()
331 debug("");
332 debug("Testing rendering with different colors in fragment shader");
334 let width = 256;
335 let height = 256;
337 let views = gl.getParameter(ext.MAX_VIEWS_OVR);
339 let multiviewShaders = [
340 getMultiviewPassthroughVertexShader(views),
341 getMultiviewColorFragmentShader()
343 let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
344 if (!testProgram) {
345 testFailed("Compilation with extension enabled failed.");
346 return;
349 let fb = gl.createFramebuffer();
350 gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
351 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
352 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
353 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
355 gl.viewport(0, 0, width, height);
356 wtu.drawUnitQuad(gl);
357 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
359 let readFb = gl.createFramebuffer();
360 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
361 for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
362 gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
363 let expectedColor = getExpectedColor(viewIndex);
364 wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
368 function runVertexShaderRenderTest()
370 debug("");
371 debug("Testing rendering with different colors in fragment shader, different offsets in vertex shader");
373 let width = 256;
374 let height = 256;
376 let views = gl.getParameter(ext.MAX_VIEWS_OVR);
378 let multiviewShaders = [
379 getMultiviewOffsetVertexShader(views),
380 getMultiviewColorFragmentShader()
383 let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
384 if (!testProgram) {
385 testFailed("Compilation with extension enabled failed.");
386 return;
389 let fb = gl.createFramebuffer();
390 gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
391 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
392 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
393 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
395 gl.viewport(0, 0, width, height);
396 wtu.drawUnitQuad(gl);
397 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
399 let readFb = gl.createFramebuffer();
400 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
401 for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
402 gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
403 let expectedColor = getExpectedColor(viewIndex);
405 checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex);
409 function runRealisticUseCaseRenderTest()
411 debug("");
412 debug("Testing rendering with a different transformation matrix chosen from a uniform array according to ViewID");
414 let width = 256;
415 let height = 256;
417 let views = gl.getParameter(ext.MAX_VIEWS_OVR);
419 let multiviewShaders = [
420 getMultiviewRealisticUseCaseVertexShader(views),
421 getMultiviewColorFragmentShader()
424 let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true);
425 if (!testProgram) {
426 testFailed("Compilation with extension enabled failed.");
427 return;
430 let fb = gl.createFramebuffer();
431 gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
432 let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
433 gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views);
434 ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views);
436 gl.viewport(0, 0, width, height);
438 let transformLocation = gl.getUniformLocation(testProgram, 'transform');
439 let transformData = new Float32Array (views * 16);
440 for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
441 let scaleX = 1.0 / views;
442 // offsetX is the position of the left edge of the quad we want to get in normalized device coordinates
443 let offsetX = viewIndex / views * 2.0 - 1.0;
445 setupTranslateAndScaleXMatrix(transformData, viewIndex * 16, scaleX, offsetX);
447 gl.uniformMatrix4fv(transformLocation, false, transformData);
449 wtu.drawUnitQuad(gl);
450 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw");
452 let readFb = gl.createFramebuffer();
453 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb);
454 for (let viewIndex = 0; viewIndex < views; ++viewIndex) {
455 gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex);
456 let expectedColor = getExpectedColor(viewIndex);
458 checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex);
462 function runUniqueObjectTest()
464 debug("");
465 debug("Testing that getExtension() returns the same object each time");
466 gl.getExtension("OVR_multiview2").myProperty = 2;
467 webglHarnessCollectGarbage();
468 shouldBe('gl.getExtension("OVR_multiview2").myProperty', '2');
471 description("This test verifies the functionality of the OVR_multiview2 extension, if it is available.");
473 debug("");
475 if (!gl) {
476 testFailed("WebGL context does not exist");
477 } else {
478 testPassed("WebGL context exists");
480 runExtensionDisabledTest();
482 runShaderCompileTest(false);
484 debug("");
486 if (!gl.getExtension("OVR_multiview2")) {
487 testPassed("No OVR_multiview2 support -- this is legal");
488 } else {
489 testPassed("Successfully enabled OVR_multiview2 extension");
490 ext = gl.getExtension('OVR_multiview2');
492 runShaderCompileTest(true);
494 runQueryTest();
496 runDefaultFramebufferQueryTest();
498 runInvalidTextureTypeTest();
500 runFramebufferQueryTest(true);
501 runFramebufferQueryTest(false);
503 runInvalidViewsTest();
505 runDetachTest();
507 runClearTest();
509 wtu.setupUnitQuad(gl, 0, 1);
511 runFragmentShaderRenderTest();
512 runVertexShaderRenderTest();
513 runRealisticUseCaseRenderTest();
514 runUniqueObjectTest();
518 debug("");
519 var successfullyParsed = true;
520 </script>
521 <script src="../../js/js-test-post.js"></script>
523 </body>
524 </html>