<!--

/*
** 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 HD-DPI issues texture 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="4" height="4" style="width: 40px; height: 30px;"></canvas>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description();
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext("example");
var program = wtu.setupTexturedQuad(gl);

function fillInMips(gl, size) {
  // fill in the mips
  var level = 1;
  for (;;) {
    size /= 2;
    if (size < 1) {
      break;
    }
    var numBytes = size * size * 4;
    var pixels = new Uint8Array(numBytes);
    for (var jj = 0; jj < numBytes; jj += 4) {
      pixels[jj + 0] = 0;
      pixels[jj + 1] = 255;
      pixels[jj + 2] = 0;
      pixels[jj + 3] = 255;
    }
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
  }
}

function testCanvas(size) {
  debug("");
  debug("testing 2D canvas size " + size + ", " + size);

  var canvas = document.createElement("canvas");
  canvas.width = size;
  canvas.height = size;
  var ctx = canvas.getContext("2d");
  ctx.fillStyle = "rgb(0,255,0)";
  ctx.fillRect(0, 0, size, size);

  var tex = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, tex);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);

  fillInMips(gl, size);

  // Draw. If this an HD-DPI device and the 2d canvas is double res or larger
  // the implementation must scale to CSS pixels (ie, canvas.width, canvas.height)(
  // when doing the copy in texImage2D. If it has not scaled and instead done
  // a direct copy of the larger texture this test will not have created enough mips
  // and will therefore not be "texture complete" and will render in black.
  wtu.clearAndDrawUnitQuad(gl);
  wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
}

function testWebGL(size) {
  debug("");
  debug("testing WebGL canvas size " + size + ", " + size);

  var canvas = document.createElement("canvas");
  canvas.width = size;
  canvas.height = size;
  var gl2 = wtu.create3DContext(canvas);
  gl2.clearColor(0,1,0,1);
  gl2.clear(gl.COLOR_BUFFER_BIT);

  var tex = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, tex);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas);

  fillInMips(gl, size);

  // Draw. If this an HD-DPI device check for 2 possible bugs.
  //
  // 1) the WebGL canvas is double res or larger. That's just a bug period and
  //    is checked for in another test but would also fail here.
  //
  // 2) the WebGL canvas is single res but the code the scales a double res
  //    2d canvas also mistakenly scales a single res WebGL canvas.
  //
  // If it has been scaled then we'll have the wrong kind of mips chain here.
  // Level 0 will be half resolution. Level 1 will be the same resolution
  // and will therefore not be "texture complete" and will render in black.
  wtu.clearAndDrawUnitQuad(gl);
  wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green");
}

testCanvas(4);
testCanvas(512);
testWebGL(4);
testWebGL(512);
glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors");

var successfullyParsed = true;

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

</body>
</html>

