chromium/content/test/data/gpu/webgl.html

<html>
<head>
<script type="text/javascript">
var canvas;
var w, h;
var gl;
var extension;

function testHorizontalBands() {
  gl.enable(gl.SCISSOR_TEST);

  gl.clearColor(1, 0, 0, 1);
  gl.scissor(0, 0, w, h/2);
  gl.clear(gl.COLOR_BUFFER_BIT);

  gl.clearColor(0, 1, 0, 1);
  gl.scissor(0, h/2, w, h/2);
  gl.clear(gl.COLOR_BUFFER_BIT);

  gl.disable(gl.SCISSOR_TEST);

  var size = w * h * 4;
  var array = new Uint8Array(size);
  gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, array);

  return array[0] == 255 && array[1] == 0 &&
      array[size - 4] == 0 && array[size - 3] == 255;
}

function testContextLost(e) {
  e.preventDefault();
  if (extension) {
    setTimeout(function() {
      extension.restoreContext();
      extension = null;
    }, 0);
  }
}

function testContextRestored() {
  gl = canvas.getContext("experimental-webgl");
  if (!gl || gl.isContextLost()) {
    // Might just be blocked because of infobar.
    return;
  }
  gl.clearColor(0, 0, 1, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);

  var a = new Uint8Array(w * h * 4);
  gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, a);

  if (a[0] == 0 && a[1] == 0 && a[2] == 255)
    window.domAutomationController.send("SUCCESS");
  else
    window.domAutomationController.send("FAILED");
}

function testQuantityLoss() {
  var count = 0;
  var iterations = 128;
  var garbageCanvases = [];

  function createAndDiscardContext() {
    count++;

    var c = document.createElement("canvas");
    c.width = 1;
    c.height = 1;
    garbageCanvases.push(c);

    var ctx = c.getContext("experimental-webgl");
    if (!ctx) {
      console.log("Failed to fetch WebGL context number " + count);
      window.domAutomationController.send("LOADED");
      window.domAutomationController.send("FAILED");
      return false;
    }
    ctx.clear(gl.COLOR_BUFFER_BIT);

    if (count < iterations) {
      window.requestAnimationFrame(createAndDiscardContext);
    } else {
      // Remove the references to the garbage canvases, then attempt to trigger
      // a garbage collect.
      garbageCanvases = null;

      window.domAutomationController.send("LOADED");

      // Trying to provoke garbage collection through excessive allocations.
      setInterval(function() {
        var garbageArray = new Uint8Array(1024 * 1024);
        garbageArray[0] = 255;
      }, 10);
    }
  };

  createAndDiscardContext();
}

function getLoseContextExtension()
{
    return gl.getExtension("WEBKIT_WEBGL_lose_context") ||
           gl.getExtension("WEBGL_lose_context");
}

function loseContextUsingExtension()
{
    getLoseContextExtension().loseContext();
    // Report success at the next frame to give the compositor a chance to draw
    // using the lost context.
    window.requestAnimationFrame(function() {
        window.domAutomationController.send("SUCCESS");
    });
}

function contextLostTest(kind)
{
  switch (kind) {
    case "WEBGL_lose_context": {
      extension = getLoseContextExtension();
      extension.loseContext();
      break;
    }
    case "kill":
      // nothing -- the browser test navigates to about:gpucrash and kills
      // the GPU process.
      break;
    case "kill_after_notification":
      // The browser test waits for notification from the page that it
      // has been loaded before navigating to about:gpucrash.
      window.domAutomationController.send("LOADED");
      break;
    case "forced_quantity_loss":
      // Test creates many new contexts, forcing the original context to be
      // lost. Then a garbage collect is triggered and the original context is
      // watched to ensure it restores properly.
      testQuantityLoss();
      break;
  }
}

function onLoad() {
  canvas = document.getElementById("canvas1");
  w = canvas.width;
  h = canvas.height;
  if (!canvas)
    return;
  canvas.addEventListener("webglcontextlost", testContextLost, false);
  canvas.addEventListener("webglcontextrestored", testContextRestored, false);

  gl = canvas.getContext("experimental-webgl");
  if (!gl)
    return;

  if (!testHorizontalBands())
    return;

  const query = new URLSearchParams(window.location.search).get('query');
    if (query)
      contextLostTest(query);
}
</script>
</head>
<body onload="onLoad()">
<canvas id="canvas1" width="16px" height="32px">
</canvas>
</body>
</html>