<!--

/*
** 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 Big FBO Test</title>
<link rel="stylesheet" href="../resources/js-test-style.css"/>
<script src="../../debug/webgl-debug.js"></script>
<script src="../resources/js-test-pre.js"></script>
<script src="../conformance/resources/webgl-test-utils.js"></script>
</head>
<body>
<canvas id="canvas" width="256" height="256"> </canvas>
<div id="description"></div>
<div id="console"></div>
<script id="vshader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec2 texCoord0;
varying vec2 texCoord;
void main()
{
  gl_Position = vec4(vPosition.xyz, 1.0);
  texCoord = texCoord0;
}
</script>

<script id="fshader" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D tex;
varying vec2 texCoord;
void main()
{
  gl_FragColor = texture2D(tex, texCoord);
}
</script>
<script>
"use strict";
window.onload = init;

var g_textures = [];

debug("Tests the performance of using lots of large FBOs");

function init() {
  if (confirm(
      "After clicking OK your machine may become unresponsive or crash.")) {
    main();
  } else {
    debug("cancelled");
  }
}

function checkFBOStatus(gl) {
  var err = gl.getError();
  if (err != gl.NO_ERROR) {
    if (err != gl.OUT_OF_MEMORY)
      testFailed("gl.getError returned " + err);
    else
      testPassed("OUT-OF-MEMORY");
    return false;
  }
  var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
  if (status != gl.FRAMEBUFFER_COMPLETE) {
    testFailed("gl.checkFramebufferStatus() returned " + WebGLDebugUtils.glEnumToString(status));
    return false;
  }
  return true;
}

function setupFBO(gl, size) {
  var tex = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, tex);
  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);

  var fb = gl.createFramebuffer();
  gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);

  gl.texImage2D(gl.TEXTURE_2D,
                0,                 // level
                gl.RGBA,           // internalFormat
                size,              // width
                size,              // height
                0,                 // border
                gl.RGBA,           // format
                gl.UNSIGNED_BYTE,  // type
                null);             // data
  if (!checkFBOStatus(gl))
    return null;

  return { fb: fb, tex: tex };
}

function checkPixels(gl) {
  var width = 256;
  var height = 256;

  var thresh = 3;

  var buf = new Uint8Array(width * height * 4);
  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
  for (var yy = 0; yy < height; ++yy) {
    for (var xx = 0; xx < width; ++xx) {
      var offset = (yy * width + xx) * 4;
      if (Math.abs(buf[offset] - 255) > thresh ||
          Math.abs(buf[offset + 1] - 0) > thresh ||
          Math.abs(buf[offset + 2] - 0) > thresh) {
        testFailed("drawing results incorrect");
        return false;
      }
    }
  }
  return true;
}

function handleContextLost() {
  debug("context lost");
}

function main() {
  debug("");
  debug("Checking for out of memory handling.");

  var canvas = document.getElementById("canvas");
  canvas.addEventListener('webglcontextlost', handleContextLost);
  var wtu = WebGLTestUtils;
  var gl = wtu.create3DContext("canvas");
  var prog = wtu.setupProgram(gl, ["vshader", "fshader"], ["vPosition", "texCoord0"]);

  WebGLDebugUtils.init(gl);

  gl.disable(gl.DEPTH_TEST);
  gl.disable(gl.BLEND);

  var vertexObject = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
    -1,1,0, 1,1,0, -1,-1,0,
    -1,-1,0, 1,1,0, 1,-1,0
  ]), gl.STATIC_DRAW);
  gl.enableVertexAttribArray(0);
  gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);

  var vertexObject = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0, 1,0, 0,1,
    0,1, 1,0, 1,1
  ]), gl.STATIC_DRAW);
  gl.enableVertexAttribArray(1);
  gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);

  var texLoc = gl.getUniformLocation(prog, "tex");
  gl.uniform1i(texLoc, 0);

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

  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup should succeed");

  var size = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
  debug("max render buffer size: " + size +
        ", size used: " + (size / 2));
  size /= 2;

  var maxFBOs = 200;
  var numFBOs = 0;
  allocateNextFBO();

  function allocateNextFBO() {
    if (numFBOs >= maxFBOs) {
      phase2();
      return;
    }
    if (!allocateFBO()) {
      phase2();
      return;
    }
    ++numFBOs;
    setTimeout(allocateNextFBO, 100);
  }

  function allocateFBO() {
    debug("");
    debug("trying to create fbo #" + (numFBOs + 1));
    var t = setupFBO(gl, 2);
    if (!t) {
      return false;
    }

    var tex = t.tex;
    var fb = t.fb;

    debug("allocating fbo color buffer of size " + size + " x " + size);
    gl.texImage2D(gl.TEXTURE_2D,
                  0,                 // level
                  gl.RGBA,           // internalFormat
                  size,              // width
                  size,              // height
                  0,                 // border
                  gl.RGBA,           // format
                  gl.UNSIGNED_BYTE,  // type
                  null);             // data
    if (!checkFBOStatus(gl)) {
      return false;
    }
    g_textures.push(tex);
    debug("succeeded in creating fbo");

    debug("clearing the fbo with red color");
    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    gl.clearColor(1, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);

    debug("deleting fbo, but the now red texture should be untouched");
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    gl.deleteFramebuffer(fb);

    debug("drawing to the canvas using the red texture");
    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 6);
    if (!checkPixels(gl)) {
      return false;
    }

    debug("succeeded in drawing");
    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "each run with no error");
    return true;
  }

  function phase2() {
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

    debug("");
    debug("fbos allocated:" + numFBOs);
    if (!checkPixels(gl)) {
      testFailed("final check of canvas drawing buffer pixels failed");
    }
    debug("");
    finishTest();
  }
}

var successfullyParsed = true;
</script>

</body>
</html>
