<!DOCTYPE HTML>
<title>WebGL fuzzy bugs</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<script src="driver-info.js"></script>
<script src="webgl-util.js"></script>
<body>
<script>

// Test the framebufferTexture2D() call with a unbound texture.
function framebufferTexture2D_bug1257593() {
  var canvas = document.createElement('canvas');

  var gl = null;
  gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  if (!gl) {
    todo(false, 'WebGL framebufferTexture2D test, webgl is unavailable.');
    return;
  }

  var texture = gl.createTexture(); // only createTexture(), but no bindBuffer()
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, texture, 0);

  ok(true, 'WebGL framebufferTexture2D with unbound texture');
}

// Test to call ClearBufferXXX() during context lost.
function webGL2ClearBufferXXX_bug1252414() {
  var canvas = document.createElement('canvas');

  var gl = canvas.getContext('webgl2');
  if (!gl) {
    todo(false, 'WebGL2 is not supported');
    return;
  }

  var ext = gl.getExtension('WEBGL_lose_context');
  if (!ext) {
    todo(false, 'WebGL ClearBufferXXX test, ext WEBGL_lose_context is unavailable.');
    return;
  }

  // Force to lose context.
  ext.loseContext();

  // Even thought the context is lost, all clearBuffer* function should still
  // work without crash.
  gl.clearBufferiv(gl.COLOR, 0, new Int32Array(10));
  gl.clearBufferuiv(gl.COLOR, 0, new Uint32Array(10));
  gl.clearBufferfv(gl.DEPTH, 0, new Float32Array(10));
  gl.clearBufferfi(gl.DEPTH_STENCIL, 0, 0.0, 0);

  ok(true, 'WebGL2 clearBufferXXX call during loseContext');
}

// Test gl function for multiple gl contexts switch.
function getFramebufferAttachmentParameter_bug1267100()
{
  var canvas1 = document.createElement('canvas');
  var canvas2 = document.createElement('canvas');

  var gl1 = null;
  gl1 = canvas1.getContext('webgl') || canvas1.getContext('experimental-webgl');
  if (!gl1) {
    todo(false, 'WebGL getFramebufferAttachmentParameter test, webgl is unavailable.');
    return;
  }
  var gl2 = null;
  gl2 = canvas2.getContext('webgl') || canvas2.getContext('experimental-webgl');
  if (!gl2) {
    todo(false, 'WebGL getFramebufferAttachmentParameter test, webgl is unavailable.');
    return;
  }

  gl1.bindFramebuffer(gl1.FRAMEBUFFER, gl1.createFramebuffer());
  gl2.scissor(0, 1, 2, 3);
  // The gl call should still work even though we use another gl context before.
  gl1.getFramebufferAttachmentParameter(gl1.FRAMEBUFFER,
                                        gl1.COLOR_ATTACHMENT0,
                                        gl1.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);

  ok(true, 'WebGL test getFramebufferAttachmentParameter');
}

// Test to call getFragDataLocation() when the fragment shader is detatched.
function getFragDataLocation_bug1259702() {
  var canvas = document.createElement('canvas');

  var gl = canvas.getContext('webgl2');

  if (!gl) {
    todo(false, 'WebGL2 is not supported');
    return;
  }

  var program = gl.createProgram();

  var vertexShaderSrc =
    "void main(void) { \
       gl_Position = vec4(1.0, 1.0, 1.0, 1.0); \
    }";
  var fragmentShaderSrc =
    "void main(void) { \
       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); \
    }";

  var vertexShader = gl.createShader(gl.VERTEX_SHADER);
  var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

  gl.shaderSource(vertexShader, vertexShaderSrc);
  gl.compileShader(vertexShader);
  gl.attachShader(program, vertexShader);

  gl.shaderSource(fragmentShader, fragmentShaderSrc);
  gl.compileShader(fragmentShader);
  gl.attachShader(program, fragmentShader);

  gl.linkProgram(program);
  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    var lastError = gl.getProgramInfoLog(program);
    ok(false, 'WebGL getFragDataLocation() test, error in linking:' +
        lastError);
    return;
  }

  gl.useProgram(program);

  gl.detachShader(program, fragmentShader);
  // Test the getFragDataLocation() call after detatch the shader.
  // This call should not hit crash.
  gl.getFragDataLocation(program, "foobar");

  ok(true, 'WebGL getFragDataLocation() call after detatch fragment shader');
}

function deleteBuffer_bug1379995()
{
  var canvas = document.createElement('canvas');
  var gl = null;
  gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  if (!gl) {
    todo(false, 'WebGL deleteBuffer test, webgl is unavailable.');
    return;
  }

  var program = gl.createProgram();
  var vShader = gl.createShader(gl.VERTEX_SHADER);
  var fShader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(vShader,'attribute vec3 pos;void main(){gl_Position = vec4(pos, 2.0);}');
  gl.shaderSource(fShader,'void main() {gl_FragColor = vec4(0.5, 0.5, 1.0, 1.0);}');
  gl.compileShader(vShader);
  gl.compileShader(fShader);
  gl.attachShader(program, vShader);
  gl.attachShader(program, fShader);
  gl.linkProgram(program);
  var buffer = gl.createBuffer();
  var attr = gl.getAttribLocation(program, 'pos');
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.enableVertexAttribArray(attr);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, 0, 0,0, 1, 0,0, -1, 0,1, 0, 0]),gl.STATIC_DRAW);
  gl.useProgram(program);
  gl.vertexAttribPointer(attr, 3, gl.FLOAT, false, 0, 0);
  gl.drawArrays(gl.TRIANGLES, 0, 3);
  gl.deleteBuffer(buffer);
  // Call the drawArrays after deleteBuffer(). It should not hit the crash.
  gl.drawArrays(gl.TRIANGLES, 0, 3);

  ok(true, 'WebGL no crash for drawArrays() after deleteBuffer() call');
}

function run() {
  webGL2ClearBufferXXX_bug1252414();
  framebufferTexture2D_bug1257593();
  getFramebufferAttachmentParameter_bug1267100();
  getFragDataLocation_bug1259702();
  deleteBuffer_bug1379995();

  SimpleTest.finish();
}

SimpleTest.waitForExplicitFinish();

try {
  var prefArrArr = [
    ['webgl.force-enabled', true],
    ['webgl.enable-webgl2', true],
  ];
  var prefEnv = {'set': prefArrArr};
  SpecialPowers.pushPrefEnv(prefEnv, run);
} catch (e) {
  warning('No SpecialPowers, but trying WebGL2 anyway...');
  run();
}
</script>

