diff options
Diffstat (limited to '')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2.html | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2.html new file mode 100644 index 0000000000..ba74d1398b --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/ovr_multiview2.html @@ -0,0 +1,524 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL OVR_multiview2 Conformance Tests</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +<script src="../../js/tests/ovr_multiview2_util.js"></script> +<script id="requireDefine_GL_OVR_multiview2" type="x-shader/x-fragment">#version 300 es +#ifndef GL_OVR_multiview2 + #error no GL_OVR_multiview2 +#endif +precision highp float; +out vec4 my_FragColor; +void main() { + my_FragColor = vec4(0.0, 1.0, 0.0, 1.0); +} +</script> +<script id="forbidDefine_GL_OVR_multiview" type="x-shader/x-fragment">#version 300 es +#ifdef GL_OVR_multiview + #error legacy GL_OVR_multiview support must be forbidden +#endif +precision highp float; +out vec4 my_FragColor; +void main() { + my_FragColor = vec4(0.0, 1.0, 0.0, 1.0); +} +</script> +<script id="legacyMultiview1Shader" type="x-shader/x-fragment">#version 300 es +#extension GL_OVR_multiview: require +precision highp float; +out vec4 my_FragColor; +void main() { + my_FragColor = vec4(0.0, 1.0, 0.0, 1.0); +} +</script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; + +let wtu = WebGLTestUtils; +let gl = wtu.create3DContext(null, null, 2); +let ext = null; + +function runExtensionDisabledTest() +{ + debug(""); + debug("Testing queries with extension disabled"); + + let maxViews = gl.getParameter(0x9631); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query MAX_VIEWS_OVR without enabling OVR_multiview2"); + + let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9630); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR without enabling OVR_multiview2"); + let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, 0x9632); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "Can't query FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR without enabling OVR_multiview2"); +} + +function runQueryTest() +{ + debug(""); + debug("Testing querying MAX_VIEWS_OVR"); + + let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from querying MAX_VIEWS_OVR"); + if (typeof maxViews != 'number') { + testFailed("Type of the value of MAX_VIEWS_OVR should be number, was " + (typeof maxViews)); + } + if (maxViews < 2) { + testFailed("Value of MAX_VIEWS_OVR should be at least two, was: " + maxViews); + } +} + +function runDefaultFramebufferQueryTest() +{ + debug(""); + debug("Testing querying base view index and num views on the default framebuffer"); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + // Same behavior as FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR is INVALID_ENUM for default framebuffer"); + gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR is INVALID_ENUM for default framebuffer"); +} + +function runInvalidTextureTypeTest() +{ + debug(""); + debug("Testing invalid texture types"); + let tex2D = createTextureWithNearestFiltering(gl.TEXTURE_2D); + gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 128, 128); + ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex2D, 0, 0, 1); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 2D texture"); + + let texCube = createTextureWithNearestFiltering(gl.TEXTURE_CUBE_MAP); + gl.texStorage2D(gl.TEXTURE_CUBE_MAP, 1, gl.RGBA8, 128, 128); + ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texCube, 0, 0, 1); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a cube map texture"); + + let tex3D = createTextureWithNearestFiltering(gl.TEXTURE_3D); + gl.texStorage3D(gl.TEXTURE_3D, 1, gl.RGBA8, 128, 128, 2); + ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex3D, 0, 0, 2); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "should not be possible to create a multiview framebuffer against a 3D texture"); +} + +/** + * If allocateStorage is true, the test will allocate texture storage. If it is false, attachments are done without allocations. + */ +function runFramebufferQueryTest(allocateStorage) +{ + debug(""); + debug("Testing querying attachment object type, baseViewIndex, numViews and framebuffer status. Texture storage is " + (allocateStorage ? "allocated" : "not allocated") + "."); + + let checkQueryResult = function(actual, expected, name) { + if (actual != expected) { + testFailed('Unexpected ' + name + ': ' + actual + ' when it was set to ' + expected); + } else { + testPassed(name + ' was ' + actual + ' when queried from the framebuffer'); + } + } + + let setupAndQuery = function(colorTex, levelSet, baseViewIndexSet, numViewsSet) { + ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, levelSet, baseViewIndexSet, numViewsSet); + let objectType = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + if (objectType != gl.TEXTURE) { + testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ', should be TEXTURE'); + } else { + testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was TEXTURE'); + } + + let level = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL); + checkQueryResult(level, levelSet, "level"); + + let textureName = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME); + checkQueryResult(textureName, colorTex, "texture object"); + + let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR); + checkQueryResult(baseViewIndex, baseViewIndexSet, "baseViewIndex"); + + let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR); + checkQueryResult(numViews, numViewsSet, "numViews"); + + let layer = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER); + checkQueryResult(layer, baseViewIndexSet, "texture layer (should match baseViewIndex)"); + } + + let setupSecondAttachmentAndQueryStatus = function(colorTex2, baseViewIndex, numViews, expectedStatus, msg) { + ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, colorTex2, 0, baseViewIndex, numViews); + let status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + if (status != expectedStatus) { + testFailed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' did not match with the expected value: ' + wtu.glEnumToString(gl, expectedStatus) + ' - ' + msg); + } else { + testPassed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' matched with the expected value - ' + msg); + } + } + + let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR); + + let fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + let baseViewIndex = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying baseViewIndex from a nonexistent attachment"); + if (baseViewIndex != null) { + testFailed('Unexpected baseViewIndex ' + baseViewIndex + ' on a framebuffer without attachments'); + } else { + testPassed('Querying baseViewIndex returned null on a framebuffer without attachments'); + } + let numViews = gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, ext.FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Querying numViews from a nonexistent attachment"); + if (numViews != null) { + testFailed('Unexpected numViews ' + numViews + ' on a framebuffer without attachments'); + } else { + testPassed('Querying numViews returned null on a framebuffer without attachments'); + } + + let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); + if (allocateStorage) { + gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 2, gl.RGBA8, 128, 128, maxViews); + } + setupAndQuery(colorTex, 0, 0, maxViews); + setupAndQuery(colorTex, 1, 0, 2); + setupAndQuery(colorTex, 0, 1, maxViews - 1); + + // Test matching and mismatching attachments for framebuffer status. + let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); + if (allocateStorage) { + gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, 128, 128, maxViews); + } + setupSecondAttachmentAndQueryStatus(colorTex2, 1, maxViews - 1, allocateStorage ? gl.FRAMEBUFFER_COMPLETE : gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 'matching baseViewIndex and numViews on different attachments'); + if (allocateStorage) { + setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'baseViewIndex mismatch'); + ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews); + setupSecondAttachmentAndQueryStatus(colorTex2, 0, maxViews - 1, ext.FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 'numViews mismatch'); + } + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from framebuffer queries"); +} + +function runInvalidViewsTest() +{ + debug(""); + debug("Testing invalid out-of-range values for baseViewIndex and numViews"); + + let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR); + let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS); + + let fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb); + let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); + // Don't allocate storage since it's not needed for the validation. + ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews + 1); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified too many views"); + ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified zero views"); + ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, -1, 2); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified negative baseViewIndex"); + + let colorTex2 = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); + ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews + 1, maxViews); + // baseViewIndex + numViews = (maxLayers - maxViews + 1) + maxViews = maxLayers + 1 + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "Specified so many views that baseViewIndex + numViews is greater than MAX_ARRAY_TEXTURE_LAYERS"); + ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex2, 0, maxLayers - maxViews, maxViews); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex + numViews is exactly MAX_ARRAY_TEXTURE_LAYERS"); +} + +function runDetachTest() +{ + debug(""); + debug("Testing detaching multiview attachments"); + + let maxViews = gl.getParameter(ext.MAX_VIEWS_OVR); + let maxLayers = gl.getParameter(gl.MAX_ARRAY_TEXTURE_LAYERS); + + let fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb); + let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); + ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews); + ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, null, 0, maxLayers + 1, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "baseViewIndex and numViews are not validated when detaching"); + let objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + if (objectType != gl.NONE) { + testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE'); + } else { + testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach'); + } + + ext.framebufferTextureMultiviewOVR(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, maxViews); + gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Can detach with framebufferTexture2D as well."); + objectType = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + if (objectType != gl.NONE) { + testFailed('Unexpected FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE ' + wtu.glEnumToString(gl, objectType) + ' after detach, should be NONE'); + } else { + testPassed('FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE was NONE after detach'); + } +} + +function runShaderCompileTest(extensionEnabled) +{ + debug(""); + debug("Testing shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled")); + + let prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "requireDefine_GL_OVR_multiview2"], undefined, undefined, true); + expectTrue(!extensionEnabled == !prog, + "GL_OVR_multiview2 must be defined by the preprocessor iff OVR_multiview2 is enabled by getExtension."); + if (extensionEnabled) { + prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "forbidDefine_GL_OVR_multiview"], undefined, undefined, true); + expectTrue(prog, "GL_OVR_multiview must never be defined by the preprocessor."); + + prog = wtu.setupProgram(gl, [wtu.simpleVertexShaderESSL300, "legacyMultiview1Shader"], undefined, undefined, true); + expectTrue(!prog, "#extension GL_OVR_multiview must be forbidden."); + } + + if (!extensionEnabled) { + let multiviewShaders = [ + getMultiviewPassthroughVertexShader(2), + getMultiviewColorFragmentShader() + ]; + let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true); + if (testProgram) { + testFailed("Compilation of shaders using extension functionality succeeded when the extension is disabled, should fail."); + } else { + testPassed("Compilation of shaders using extension functionality should fail when the extension is disabled."); + } + } +} + +function runClearTest() +{ + debug(""); + debug("Testing that calling clear() clears all views"); + + let width = 256; + let height = 256; + + let views = gl.getParameter(ext.MAX_VIEWS_OVR); + + let fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); + gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views); + ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views); + + gl.viewport(0, 0, width, height); + + gl.clearColor(0, 1, 1, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from clear"); + + let readFb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb); + for (let viewIndex = 0; viewIndex < views; ++viewIndex) { + gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex); + let expectedColor = [0, 255, 255, 255]; + wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be cyan'); + } +} + +function runFragmentShaderRenderTest() +{ + debug(""); + debug("Testing rendering with different colors in fragment shader"); + + let width = 256; + let height = 256; + + let views = gl.getParameter(ext.MAX_VIEWS_OVR); + + let multiviewShaders = [ + getMultiviewPassthroughVertexShader(views), + getMultiviewColorFragmentShader() + ]; + let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true); + if (!testProgram) { + testFailed("Compilation with extension enabled failed."); + return; + } + + let fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); + gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views); + ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views); + + gl.viewport(0, 0, width, height); + wtu.drawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw"); + + let readFb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb); + for (let viewIndex = 0; viewIndex < views; ++viewIndex) { + gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex); + let expectedColor = getExpectedColor(viewIndex); + wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor); + } +} + +function runVertexShaderRenderTest() +{ + debug(""); + debug("Testing rendering with different colors in fragment shader, different offsets in vertex shader"); + + let width = 256; + let height = 256; + + let views = gl.getParameter(ext.MAX_VIEWS_OVR); + + let multiviewShaders = [ + getMultiviewOffsetVertexShader(views), + getMultiviewColorFragmentShader() + ]; + + let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true); + if (!testProgram) { + testFailed("Compilation with extension enabled failed."); + return; + } + + let fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); + gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views); + ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views); + + gl.viewport(0, 0, width, height); + wtu.drawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw"); + + let readFb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb); + for (let viewIndex = 0; viewIndex < views; ++viewIndex) { + gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex); + let expectedColor = getExpectedColor(viewIndex); + + checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex); + } +} + +function runRealisticUseCaseRenderTest() +{ + debug(""); + debug("Testing rendering with a different transformation matrix chosen from a uniform array according to ViewID"); + + let width = 256; + let height = 256; + + let views = gl.getParameter(ext.MAX_VIEWS_OVR); + + let multiviewShaders = [ + getMultiviewRealisticUseCaseVertexShader(views), + getMultiviewColorFragmentShader() + ]; + + let testProgram = wtu.setupProgram(gl, multiviewShaders, ['a_position'], [0], true); + if (!testProgram) { + testFailed("Compilation with extension enabled failed."); + return; + } + + let fb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + let colorTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY); + gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.RGBA8, width, height, views); + ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, 0, views); + + gl.viewport(0, 0, width, height); + + let transformLocation = gl.getUniformLocation(testProgram, 'transform'); + let transformData = new Float32Array (views * 16); + for (let viewIndex = 0; viewIndex < views; ++viewIndex) { + let scaleX = 1.0 / views; + // offsetX is the position of the left edge of the quad we want to get in normalized device coordinates + let offsetX = viewIndex / views * 2.0 - 1.0; + + setupTranslateAndScaleXMatrix(transformData, viewIndex * 16, scaleX, offsetX); + } + gl.uniformMatrix4fv(transformLocation, false, transformData); + + wtu.drawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw"); + + let readFb = gl.createFramebuffer(); + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, readFb); + for (let viewIndex = 0; viewIndex < views; ++viewIndex) { + gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, colorTex, 0, viewIndex); + let expectedColor = getExpectedColor(viewIndex); + + checkVerticalStrip(width, height, views, viewIndex, expectedColor, 'view ' + viewIndex); + } +} + +function runUniqueObjectTest() +{ + debug(""); + debug("Testing that getExtension() returns the same object each time"); + gl.getExtension("OVR_multiview2").myProperty = 2; + webglHarnessCollectGarbage(); + shouldBe('gl.getExtension("OVR_multiview2").myProperty', '2'); +} + +description("This test verifies the functionality of the OVR_multiview2 extension, if it is available."); + +debug(""); + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + + runExtensionDisabledTest(); + + runShaderCompileTest(false); + + debug(""); + + if (!gl.getExtension("OVR_multiview2")) { + testPassed("No OVR_multiview2 support -- this is legal"); + } else { + testPassed("Successfully enabled OVR_multiview2 extension"); + ext = gl.getExtension('OVR_multiview2'); + + runShaderCompileTest(true); + + runQueryTest(); + + runDefaultFramebufferQueryTest(); + + runInvalidTextureTypeTest(); + + runFramebufferQueryTest(true); + runFramebufferQueryTest(false); + + runInvalidViewsTest(); + + runDetachTest(); + + runClearTest(); + + wtu.setupUnitQuad(gl, 0, 1); + + runFragmentShaderRenderTest(); + runVertexShaderRenderTest(); + runRealisticUseCaseRenderTest(); + runUniqueObjectTest(); + } +} + +debug(""); +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> |