<!--
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 uniform values are per program conformance test.</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>
<script id="vshader" type="x-shader/x-vertex">
attribute vec4 a_position;
void main() {
  gl_Position = a_position;
}
</script>
<script id="fshader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 v_color;
void main() {
  gl_FragColor = v_color;
}
</script>
<script id="vshaderTest" type="x-shader/x-vertex">
attribute vec4 a_position;
uniform $(type) $(name1);
uniform $(type) $(name2);
uniform bool u_select;
varying vec4 v_color;
void main() {
  $(type) value = u_select ? $(name2) : $(name1);
  v_color = $(conversion);
  gl_Position = a_position;
}
</script>
<script id="fshaderTest" type="x-shader/x-fragment">
precision mediump float;
uniform $(type) $(name1);
uniform $(type) $(name2);
uniform bool u_select;
void main() {
  $(type) value = u_select ? $(name2) : $(name1);
  gl_FragColor = $(conversion);
}
</script>
<canvas id="example" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
function init() {
  description();

  var console = document.getElementById("console");
  var wtu = WebGLTestUtils;
  var gl = wtu.create3DContext("example");
  wtu.setupUnitQuad(gl);
  var vtemplate = wtu.getScript("vshader");
  var ftemplate = wtu.getScript("fshader");
  var vtemplateTest = wtu.getScript("vshaderTest");
  var ftemplateTest = wtu.getScript("fshaderTest");

  var shaders = [
    [vtemplate, ftemplateTest],
    [vtemplateTest, ftemplate],
  ];

  var names = [
    ["u_value1", "u_value2"],
    ["a", "b"],
    ["x", "y"],
    ["y", "z"],
    ["y", "u"],
    ["a00000", "a00001"],
  ];
  var testList = [
    { type: "float",
      conversion: "vec4(value, 0, 0, 0)",
      values: [[64], [128]],
      func: 'uniform1fv',
    },
    { type: "vec2",
      conversion: "vec4(value, 0, 0)",
      values: [[64, 128], [128, 64]],
      func: 'uniform2fv',
    },
    { type: "vec3",
      conversion: "vec4(value, 0)",
      values: [[64, 128, 192], [192, 128, 64]],
      func: 'uniform3fv',
    },
    { type: "vec4",
      conversion: "vec4(value)",
      values: [[64, 128, 192, 255], [255, 192, 128, 64]],
      func: 'uniform4fv',
    },
  ];

  var clone = function(obj) {
    var n = { };
    for (var $key in obj) {
      n[$key] = obj[$key];
    }
    return n;
  };

  var tests = [];
  names.forEach(function(namePair) {
    testList.forEach(function(test) {
      var t = clone(test);
      t.name1 = namePair[0];
      t.name2 = namePair[1];
      tests.push(t);
    });
  });

  var runTest = function(test) {
    debug("");
    debug("testing: " + test.type);
    shaders.forEach(function(shaderPair) {
      var progs = [];
      for (var ii = 0; ii < 2; ++ii) {
        var vsource = wtu.replaceParams(shaderPair[0], test);
        var fsource = wtu.replaceParams(shaderPair[1], test);
        if (!ii) {
          wtu.addShaderSource(console, "vertex shader: type = " + test.type + " with names " + test.name1 + ", " + test.name2, vsource);
          wtu.addShaderSource(console, "fragment shader: type = " + test.type + " with names " + test.name1 + ", " + test.name2, fsource);
        }
        var program = wtu.setupProgram(gl, [vsource, fsource], ["a_position"]);
        var info = {
          program: program,
          valueLocs: [gl.getUniformLocation(program, test.name1),
                      gl.getUniformLocation(program, test.name2)],
          selectLoc: gl.getUniformLocation(program, "u_select"),
        };
        var v1 = test.values[0];
        var v2 = test.values[1];
        if (ii) {
          var t = v1;
          v1 = v2;
          v2 = t;
        }
        info.expect = [v1, v2];
        for (var jj = 0; jj < 2; ++jj) {
          var input = info.expect[jj].map(function(v) { return v / 255; });
          gl[test.func](info.valueLocs[jj], input);
        }
        progs.push(info);
      }
      for (var ii = 0; ii < 2; ++ii) {
        progs.forEach(function(info) {
          gl.useProgram(info.program);
          gl.uniform1i(info.selectLoc, ii);
          wtu.clearAndDrawUnitQuad(gl);
          wtu.checkCanvas(gl, info.expect[ii], undefined, 1);
        });
      }
      progs.forEach(function(info) {
        gl.deleteProgram(info.program);
      });
    });
  }
  tests.forEach(function(test){
    runTest(test);
  });
}
init();
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>

