<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<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" +
  " works with stencil for immersive";
let nonImmersiveTestName = "Ensure that the framebuffer given by the WebGL layer" +
  " works with stencil for non-immersive";

let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE;

function createShader(gl, type, source) {
  var shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);
  var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  if (success) {
    return shader;
  }

  gl.deleteShader(shader);
}

function createProgram(gl, vertexShader, fragmentShader) {
  var program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);
  var success = gl.getProgramParameter(program, gl.LINK_STATUS);
  if (success) {
    return program;
  }

  gl.deleteProgram(program);
}

let testFunction =
  (session, fakeDeviceController, t, sessionObjects) => new Promise((resolve, reject) => {
  const gl = sessionObjects.gl;
  const webglLayer = sessionObjects.glLayer;
  const xrFramebuffer = webglLayer.framebuffer;
  const webglCanvas = document.getElementsByTagName('canvas')[0];

  session.requestAnimationFrame((time, xrFrame) => {
    t.step(() => {
      // Make sure we're starting with a clean error slate.
      gl.getError();
      assert_equals(gl.getError(), gl.NO_ERROR, "Should not initially have any errors");

      if (session.mode === 'inline') {
        // Creating a layer with an inline session should return a framebuffer of
        // null, and as such most of these tests won't apply.
        assert_equals(xrFramebuffer, null, 'inline, fbo = null');
        // We need to set canvas size here for inline session testing, since
        // xrFramebuffer is null.
        webglCanvas.width = webglCanvas.height = 300;
        gl.bindFramebuffer(gl.FRAMEBUFFER, xrFramebuffer);
        assert_equals(gl.getError(), gl.NO_ERROR, "Binding default framebuffer for inline session");
      } else {
        assert_not_equals(xrFramebuffer, null, 'immersive, fbo != null');
        gl.bindFramebuffer(gl.FRAMEBUFFER, xrFramebuffer);
        assert_equals(gl.getError(), gl.NO_ERROR, "Binding WebGLLayer framebuffer");
      }

      // Framebuffer status must be complete inside of a XR frame callback.
      assert_equals(gl.checkFramebufferStatus(gl.FRAMEBUFFER), gl.FRAMEBUFFER_COMPLETE, "FBO complete");
    });
    gl.clearColor(1, 1, 1, 1);

    const vs = `
    attribute vec4 position;
    uniform mat4 matrix;
    void main() {
      gl_Position = matrix * position;
    }
    `;

    const fs = `
    precision mediump float;
    uniform vec4 color;
    void main() {
      gl_FragColor = color;
    }
    `;
    const vertexShader = createShader(gl, gl.VERTEX_SHADER, vs);
    const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fs);
    const program = createProgram(gl, vertexShader, fragmentShader);

    const posLoc = gl.getAttribLocation(program, 'position');
    const matLoc = gl.getUniformLocation(program, 'matrix');
    const colorLoc = gl.getUniformLocation(program, 'color');

    const buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
       0, -1,
       1,  1,
      -1,  1,
    ]), gl.STATIC_DRAW);

    gl.enableVertexAttribArray(posLoc);
    gl.vertexAttribPointer(
        posLoc,    // attribute location
        2,         // 2 value per vertex
        gl.FLOAT,  // 32bit floating point values
        false,     // don't normalize
        0,         // stride (0 = base on type and size)
        0,         // offset into buffer
    );

    let xrViewport;
    if (session.mode == 'inline') {
      xrViewport = { x: 0, y: 0, width: webglCanvas.width, height: webglCanvas.height };
    } else {
      xrViewport = { x: 0, y: 0, width: webglLayer.framebufferWidth, height: webglLayer.framebufferHeight };
    }

    gl.viewport(xrViewport.x, xrViewport.y, xrViewport.width, xrViewport.height);
    gl.scissor(xrViewport.x, xrViewport.y, xrViewport.width, xrViewport.height);

    // clear the stencil to 0 (the default)
    gl.stencilMask(0xFF);
    gl.clearStencil(0x0);
    gl.disable( gl.SCISSOR_TEST );
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);

    gl.useProgram(program);
    let m4 = [1, 0, 0, 0,
              0, 1, 0, 0,
              0, 0, 1, 0,
              0, 0, 0, 1];

    // turn on the stencil
    gl.enable(gl.STENCIL_TEST);

    // Drawing into a stencil, always passes, ref val 1, mask 0xFF
    gl.stencilFunc(
       gl.ALWAYS,
       1,
       0xFF,
    );
    // Set it to replace with the ref val (which is 1)
    gl.stencilOp(
       gl.KEEP,     // stencil test fails
       gl.KEEP,     // depth test fails
       gl.REPLACE,  // both tests pass
    );

    m4[0] = 0.2; m4[5] = 0.2; // scale x and y
    // draw a white triangle
    gl.uniform4fv(colorLoc, [1, 1, 1, 1]); // white
    gl.uniformMatrix4fv(matLoc, false, m4);
    gl.colorMask(false, false, false, false);
    gl.drawArrays(gl.TRIANGLES, 0, 3);

    gl.colorMask(true, true, true, true);

    // Stencil must be 0
    gl.stencilFunc(
       gl.EQUAL,
       0,
       0xFF,
    );
    // keep stencil unmodified during the draw pass
    gl.stencilOp(
       gl.KEEP,     // stencil test fails
       gl.KEEP,     // depth test fails
       gl.KEEP,     // both tests pass
    );

    m4[0] = 0.9; m4[5] = -0.9; // scale x and y
    // draw a large green triangle
    gl.uniform4fv(colorLoc, [0, 1, 0, 1]); // green
    gl.uniformMatrix4fv(matLoc, false, m4);
    gl.drawArrays(gl.TRIANGLES, 0, 3);

    gl.flush();
    gl.finish();
    let pixels = new Uint8Array(4);

    // check that the main color is used correctly (green)
    pixels[0] = pixels[1] = pixels[2] = pixels[3] = 30;
    gl.readPixels(xrViewport.x + xrViewport.width / 2, xrViewport.y + xrViewport.height/4, 1, 1, gl.RGB, gl.UNSIGNED_BYTE, pixels);
    if (pixels[0] == 0x0 && pixels[1] == 0xFF && pixels[2] == 0x0) { // green?
      // PASSED.
    } else if (pixels[0] == 0xFF && pixels[1] == 0xFF && pixels[2] == 0xFF) { // white?
      reject("Failed, white detected, must be green");
    } else {
      reject("Failed, readPixels (1) didn't work, gl error = " + gl.getError() + ", pixel = " +pixels[0] + " " +pixels[1] + " " +pixels[2]);
    }

    // check if stencil worked, i.e. white pixels in the center
    pixels[0] = pixels[1] = pixels[2] = pixels[3] = 20;
    gl.readPixels(xrViewport.x + xrViewport.width / 2, xrViewport.y + xrViewport.height/2, 1, 1, gl.RGB, gl.UNSIGNED_BYTE, pixels);
    if (pixels[0] == 0xFF && pixels[1] == 0xFF && pixels[2] == 0xFF) { // white?
      // PASSED.
    } else if (pixels[0] == 0x0 && pixels[1] == 0xFF && pixels[2] == 0x0) { // green?
      reject("Failed, green detected, must be white");
    } else {
      reject("Failed, readPixels (2) didn't work, gl error = " + gl.getError() + ", pixel = " +pixels[0] + " " +pixels[1] + " " +pixels[2]);
    }

    // Finished.
    resolve();
  });
});

const gl_props = { antialias: false, alpha: false, stencil: true, depth: true };

// mac has issues with readPixels from the default fbo.
// skipping this test for Mac.
if (navigator.platform.indexOf("Mac") == -1) {
  xr_session_promise_test(
    nonImmersiveTestName, testFunction, fakeDeviceInitParams, 'inline', {}, {}, gl_props, gl_props);
}

xr_session_promise_test(
  immersiveTestName, testFunction, fakeDeviceInitParams, 'immersive-vr', {}, {}, gl_props, gl_props);

</script>
