<!--

/*
** 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 Re-Compile and Re-link Shader 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>
<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
<div id="description"></div>
<div id="console"></div>
<script id="vshader" type="x-shader/x-vertex">
attribute float column;
attribute float height;
uniform float position;
void main() {
  gl_Position = vec4(mod(column - position, 1.0) * 2.0 - 1.0, height, 0, 1);
}
</script>

<script id="fshader1" type="x-shader/x-fragment">
precision mediump float;
void main() {
  gl_FragColor = vec4(1,0,0,1);
}
</script>
<script id="fshader2" type="x-shader/x-fragment">
precision mediump float;
uniform float foobar;
void main() {
  gl_FragColor = vec4(1,0,foobar,1);
}
</script>
<script id="vshaderB" type="not-js">
attribute vec2 position;
varying vec2 v_texCoord;
void main() {
  gl_Position = vec4(position, 0, 1);
  v_texCoord = vec2(position * 0.5 + 0.5);
}
</script>
<script id="fshaderB" type="not-js">
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D tex;
void main() {
  gl_FragColor = texture2D(tex, v_texCoord);
}
</script>

<script>
"use strict";
description(document.title);
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext("example");

var vsSource = document.getElementById("vshader").text;
var fs1Source = document.getElementById("fshader1").text;
var fs2Source = document.getElementById("fshader2").text;

var vsSourceB = document.getElementById("vshaderB").text;
var fsSourceB = document.getElementById("fshaderB").text;

var vShader = gl.createShader(gl.VERTEX_SHADER);
var fShader = gl.createShader(gl.FRAGMENT_SHADER);

var vShaderB = gl.createShader(gl.VERTEX_SHADER);
var fShaderB = gl.createShader(gl.FRAGMENT_SHADER);

var program = gl.createProgram();
var programB = gl.createProgram();

gl.attachShader(program, vShader);
gl.attachShader(program, fShader);

gl.attachShader(programB, vShaderB);
gl.attachShader(programB, fShaderB);

var success;
var shader;

function checkShaderStatus(s) {
  shader = s;
  shouldBeTrue("success = gl.getShaderParameter(shader, gl.COMPILE_STATUS)");
  if (!success) {
    debug("error: " + gl.getShaderInfoLog());
  }
}

var prg;
function checkProgramStatus(p) {
  prg = p;
  shouldBeTrue("success = gl.getProgramParameter(prg, gl.LINK_STATUS)");
  if (!success) {
    debug("error: " + gl.getProgramInfoLog(prg));
  }
}

for (var i = 0; i < 10; ++i) {
  gl.shaderSource(vShader, vsSource);
  gl.compileShader(vShader);
  checkShaderStatus(vShader)
  gl.shaderSource(fShader, fs1Source);
  gl.compileShader(fShader);
  checkShaderStatus(fShader)

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

  gl.shaderSource(vShaderB, vsSourceB);
  gl.compileShader(vShaderB);
  checkShaderStatus(vShaderB)
  gl.shaderSource(fShaderB, fsSourceB);
  gl.compileShader(fShaderB);
  checkShaderStatus(fShaderB)

  gl.linkProgram(programB);
  checkProgramStatus(programB)

  gl.useProgram(programB);
}

for (var i = 0; i < 10; ++i) {
  // Now change the fragment shader
  gl.shaderSource(fShader, fs2Source);
  gl.compileShader(fShader);
  checkShaderStatus(fShader)

  // And re-link
  gl.linkProgram(program);
  checkProgramStatus(program)
}

wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");

var successfullyParsed = true;
</script>
<script src="../../../js/js-test-post.js"></script>

</body>
</html>
