<!--
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="macroFragmentShader" type="x-shader/x-fragment">#version 300 es
precision highp float;
out vec4 my_FragColor;
void main() {
#ifdef GL_OVR_multiview2
    my_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
#else
    // Error expected
    #error no GL_OVR_multiview2;
#endif
}
</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 runDepthRenderTest()
{
    debug("");
    debug("Testing rendering with a depth texture array and depth test on");

    let width = 64;
    let height = 64;

    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);

    let depthTex = createTextureWithNearestFiltering(gl.TEXTURE_2D_ARRAY);
    gl.texStorage3D(gl.TEXTURE_2D_ARRAY, 1, gl.DEPTH32F_STENCIL8, width, height, views);
    ext.framebufferTextureMultiviewOVR(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, depthTex, 0, 0, views);

    let expectedStatus = gl.FRAMEBUFFER_COMPLETE;
    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));
    }  else {
        testPassed('Framebuffer status: ' + wtu.glEnumToString(gl, status) + ' matched with the expected value');
    }

    // Draw so that the depth test succeeds for all pixels.
    gl.viewport(0, 0, width, height);
    gl.enable(gl.DEPTH_TEST);
    gl.clearDepth(1.0);
    gl.clear(gl.DEPTH_BUFFER_BIT);

    wtu.drawUnitQuad(gl);
    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when depth test succeeds");

    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);
    }

    // Draw so that the depth test fails for all pixels.
    gl.clearDepth(0.0);
    gl.clearColor(0.0, 0.0, 0.0, 0.0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    wtu.drawUnitQuad(gl);
    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from draw when depth test fails");

    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, 0, 0, 0];
        wtu.checkCanvasRect(gl, 0, 0, width, height, expectedColor, 'view ' + viewIndex + ' should be colored ' + expectedColor);
    }
}

description("This test verifies drawing to depth buffers with the OVR_multiview2 extension, if it is available.");

debug("");

if (!gl) {
  testFailed("WebGL context does not exist");
} else {
  testPassed("WebGL context exists");

  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');

      wtu.setupUnitQuad(gl, 0, 1);

      runDepthRenderTest();
  }
}

debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>

</body>
</html>
