<!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>

<script>

let testName =
  "Ensure a WebGL layer's framebuffer can only be drawn to inside a XR frame";

let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE;

// Very simple program setup with no error checking.
function setupProgram(gl, vertexSrc, fragmentSrc) {
  let program = gl.createProgram();

  let vertexShader = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vertexShader, vertexSrc);
  gl.compileShader(vertexShader);
  gl.attachShader(program, vertexShader);

  let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fragmentShader, fragmentSrc);
  gl.compileShader(fragmentShader);
  gl.attachShader(program, fragmentShader);

  gl.linkProgram(program);
  gl.useProgram(program);

  return program;
}

let testFunction =
  (session, fakeDeviceController, t, sessionObjects) => new Promise((resolve, reject) => {
  let gl = sessionObjects.gl;
  let webglLayer = sessionObjects.glLayer;
  // Setup simple WebGL geometry to draw with.
  let program = setupProgram(gl,
    "attribute vec4 vPosition; void main() { gl_Position = vPosition; }",
    "void main() { gl_FragColor = vec4(1.0,0.0,0.0,1.0); }"
  );

  let vertexObject = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
  gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]),
    gl.STATIC_DRAW);
  gl.enableVertexAttribArray(0);
  gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);

  let indexObject = gl.createBuffer();
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject);
  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2]), gl.STATIC_DRAW);

  let xrFramebuffer = webglLayer.framebuffer;

  function runDrawTests(expectedError) {
    // Make sure we're starting with a clean error slate.
    assert_equals(gl.getError(), gl.NO_ERROR);

    gl.bindFramebuffer(gl.FRAMEBUFFER, xrFramebuffer);
    assert_equals(gl.getError(), gl.NO_ERROR);

    gl.clear(gl.COLOR_BUFFER_BIT);
    assert_equals(gl.getError(), gl[expectedError]);

    gl.clear(gl.DEPTH_BUFFER_BIT);
    assert_equals(gl.getError(), gl[expectedError]);

    gl.drawArrays(gl.TRIANGLES, 0, 3);
    assert_equals(gl.getError(), gl[expectedError]);

    gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_BYTE, 0);
    assert_equals(gl.getError(), gl[expectedError]);
  }

  // Drawing operations outside of a XR frame should fail.
  runDrawTests("INVALID_FRAMEBUFFER_OPERATION");

  // Drawing operations within a XR frame should succeed.
  session.requestAnimationFrame((time, xrFrame) => {
    runDrawTests("NO_ERROR");
    resolve();
  });
});

xr_session_promise_test(
  testName, testFunction, fakeDeviceInitParams, 'immersive-vr');

</script>
