<!--

/*
** Copyright (c) 2012 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/

-->

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGL ActiveTexture BindTexture conformance test.</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../resources/js-test-pre.js"></script>
<script src="../resources/webgl-test.js"> </script>
<script src="../resources/webgl-test-utils.js"></script>
</head>
<body>
<canvas id="example" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
<canvas id="canvas2d" width="1" height="1" style="width: 40px; height: 40px;"></canvas>
<div id="description"></div>
<div id="console"></div>
<script id="vshader" type="x-shader/x-vertex">
uniform mat4 world;
attribute vec3 vPosition;
attribute vec2 texCoord0;
varying vec2 texCoord;
void main()
{
  gl_Position = world * vec4(vPosition, 1);
  texCoord = texCoord0;
}
</script>
<script>
"use strict";
var gl;

function init()
{
  description(
      "Tests that glActiveTexture and glBindTexture work as expected" +
      "Specifically texture targets are per active texture unit.");

  var canvas2d = document.getElementById("canvas2d");
  var ctx2d = canvas2d.getContext("2d");

  var wtu = WebGLTestUtils;
  gl = wtu.create3DContext("example");
  var program = wtu.setupProgram(
      gl,
      ["vshader", wtu.setupSimpleTextureFragmentShader(gl)],
      ['vPosition', 'texCoord0']);
  wtu.setupUnitQuad(gl);
  gl.disable(gl.DEPTH_TEST);
  gl.disable(gl.BLEND);
  glErrorShouldBe(gl, gl.NO_ERROR);

  var colors = [
      [0,192,128,255],
      [128,64,255,255],
      [192,255,64,255],
      [200,0,255,255]];

  // Make 4 textures by using 4 active texture units if available.
  var texunits = Math.min(colors.length, gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS))
  var textures = [];
  for (var ii = 0; ii < texunits; ++ii) {
    var tex = gl.createTexture();
    gl.activeTexture(gl.TEXTURE0 + ii);
    gl.bindTexture(gl.TEXTURE_2D, tex);
    textures[ii] = tex;
  }
  glErrorShouldBe(gl, gl.NO_ERROR);

  // now use each texture unit to write into the textures,
  for (var ii = 0; ii < texunits; ++ii) {
    var c = colors[ii];
    ctx2d.fillStyle =
        "rgba(" + c[0] + "," + c[1] + "," + c[2] + "," + c[3] + ")";
    ctx2d.fillRect(0, 0, 1, 1);
    gl.activeTexture(gl.TEXTURE0 + ii);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
  }
  glErrorShouldBe(gl, gl.NO_ERROR);

  var textureLoc = gl.getUniformLocation(program, "tex");
  var worldLoc = gl.getUniformLocation(program, "world");
  glErrorShouldBe(gl, gl.NO_ERROR);

  gl.clearColor(1,0,0,1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  for (var ii = 0; ii < texunits; ++ii) {
    var x = ii % 2;
    var y = Math.floor(ii / 2);
    gl.uniform1i(textureLoc, ii);
    gl.uniformMatrix4fv(
        worldLoc, false,
        [0.5, 0, 0, 0,
         0, 0.5, 0, 0,
         0, 0, 1, 0,
         -0.5 + x, -0.5 + y, 0, 1]);
    gl.drawArrays(gl.TRIANGLES, 0, 6);
  }
  glErrorShouldBe(gl, gl.NO_ERROR);

  for (var ii = 0; ii < texunits; ++ii) {
    var c = colors[ii];
    var x = ii % 2;
    var y = Math.floor(ii / 2);
    var buf = new Uint8Array(4);
    gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
    var msg = 'expected:' +
        c[0] + ', ' + c[1] + ', ' + c[2] + ', ' + c[3] + ' found: ' +
        buf[0] + ', ' +
        buf[1] + ', ' +
        buf[2] + ', ' +
        buf[3];
    if (buf[0] != c[0] ||
        buf[1] != c[1] ||
        buf[2] != c[2] ||
        buf[3] != c[3])
      testFailed(msg);
    else
      testPassed(msg);
  }
}

init();
var successfullyParsed = true;
</script>

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

</body>
</html>

