<!--
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 Rendering Feedback Loop</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>
  </head>
  <body>
    <canvas id="example" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
    <div id="description"></div>
    <div id="console"></div>

    <script id="vs" type="text/something-not-javascript">
    attribute vec4 a_position;
    attribute vec2 a_texCoord;
    varying vec2 v_texCoord;
    void main() {
        gl_Position = a_position;
        v_texCoord = a_texCoord;
    }
    </script>
    <script id="fs" type="text/something-not-javascript">
    precision mediump float;
    varying vec2 v_texCoord;
    uniform sampler2D u_texture;
    void main() {
        // Shader swizzles color channels so we can tell if the draw succeeded.
        gl_FragColor = texture2D(u_texture, v_texCoord).gbra;
    }
    </script>
    <script>
    "use strict";
    description("Checks that rendering feedback loops fail correctly.");
    var wtu = WebGLTestUtils;
    var gl = wtu.create3DContext("example");

    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
                  new Uint8Array([255, 0, 0, 255]));
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after creating texture");

    var framebuffer = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);

    assertMsg(gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE,
        "framebuffer should be FRAMEBUFFER_COMPLETE.");

    var program = wtu.setupProgram(gl, ["vs", "fs"], ["a_position", "a_texCoord"]);
    gl.uniform1i(gl.getUniformLocation(program, "u_texture"), 0);
    gl.disable(gl.BLEND);
    gl.disable(gl.DEPTH_TEST);
    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after initWebGL");

    // Drawing with a texture that is also bound to the current framebuffer should fail
    var bufferObjects = wtu.setupUnitQuad(gl, 0, 1);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    wtu.drawUnitQuad(gl);
    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "after draw with invalid feedback loop");

    // Ensure that the texture contents did not change after the previous render
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    wtu.clearAndDrawUnitQuad(gl);
    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after drawing");
    wtu.checkCanvas(gl, [0, 0, 255, 255], "Should be blue.");

    // Drawing when texture is bound to an inactive uniform should succeed
    var texture2 = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture2);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
                  new Uint8Array([0, 255, 0, 255]));
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    gl.activeTexture(gl.TEXTURE1);
    gl.bindTexture(gl.TEXTURE_2D, texture);
    wtu.drawUnitQuad(gl);
    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "after draw where framebuffer texture is bound to inactive texture unit");
    wtu.checkCanvas(gl, [255, 0, 0, 255], "Should be red.");

    var successfullyParsed = true;
    </script>

    <script src="../../js/js-test-post.js"></script>

  </body>
</html>
