blob: 710c81a2c2bc77dce188906f245fb8bc19137a96 [file] [log] [blame]
<!--
/*
** Copyright (c) 2016 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 texture mipmap 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: 16px; height: 16px;"></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 = vPosition;
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";
var wtu = WebGLTestUtils;
var canvas = document.getElementById("example");
var gl = wtu.create3DContext(canvas, undefined, 2);
description("Test srgb emulation for generateMipmap.");
function generateMipmap()
{
debug("Generate mipmaps for sRGB texture");
wtu.setupUnitQuad(gl, 0, 1);
var program = wtu.setupProgram(
gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]);
gl.disable(gl.DEPTH_TEST);
gl.disable(gl.BLEND);
var colors = {
blank: [0, 0, 0, 0],
srgba: [0, 63, 127, 255],
};
var texLoc = gl.getUniformLocation(program, "tex");
gl.uniform1i(texLoc, 0);
var width = 128;
var height = 128;
canvas.width = width;
canvas.height = height;
gl.viewport(0, 0, width, height);
var srgbTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, srgbTex);
// Set full texture as srgba color first.
wtu.fillTexture(gl, srgbTex, width, height, colors['srgba'], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.SRGB8_ALPHA8);
// Set up-left region of the texture as red color.
// In order to make sure bi-linear interpolation operates on different colors, red region
// is 1 pixel smaller than a quarter of the full texture on each side.
var redWidth = width / 2 - 1;
var redHeight = height / 2 - 1;
var buf = new Uint8Array(redWidth * redHeight * 4);
for (var i = 0; i < redWidth * redHeight; i++) {
buf[4 * i + 0] = 255;
buf[4 * i + 1] = 0;
buf[4 * i + 2] = 0;
buf[4 * i + 3] = 255;
}
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, redWidth, redHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf);
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
// Decode the srgba texture to a linear texture which will be used as reference.
var linearTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, linearTex);
wtu.fillTexture(gl, linearTex, width, height, wtu.sRGBToLinear(colors['srgba']), 0, gl.RGBA, gl.UNSIGNED_BYTE);
// Set up-left region of the texture as red color.
// In order to make sure bi-linear interpolation operates on different colors, red region
// is 1 pixel smaller than a quarter of the full texture on each side.
for (var i = 0; i < redWidth * redHeight; i++) {
buf[4 * i + 0] = 255;
buf[4 * i + 1] = 0;
buf[4 * i + 2] = 0;
buf[4 * i + 3] = 255;
}
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, redWidth, redHeight, gl.RGBA, gl.UNSIGNED_BYTE, buf);
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
// Change canvas to a small size.
width = 64;
height = 64;
canvas.width = width;
canvas.height = height;
gl.viewport(0, 0, width, height);
// Draw with srgb texture and linear texture respectively.
gl.bindTexture(gl.TEXTURE_2D, srgbTex);
wtu.clearAndDrawUnitQuad(gl);
var result = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, result);
gl.bindTexture(gl.TEXTURE_2D, linearTex);
wtu.clearAndDrawUnitQuad(gl);
var reference = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, reference);
gl.deleteTexture(srgbTex);
gl.deleteTexture(linearTex);
var tolerance = 7;
var diff = new Uint8Array(width * height * 4);
var failed = wtu.comparePixels(result, reference, tolerance, diff);
if (failed) {
testFailed("Generate wrong mipmaps for sRGB texture.");
wtu.displayImageDiff(result, reference, diff, width, height);
} else {
testPassed("Generate correct mipmaps for sRGB texture.");
}
}
function generateMipmap_immutableTexture()
{
debug("Generate mipmaps for immutable texture.");
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texStorage2D(gl.TEXTURE_2D, Math.log2(canvas.width), gl.SRGB8_ALPHA8, canvas.width, canvas.height);
gl.generateMipmap(gl.TEXTURE_2D);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "GenerateMipmap should succeed.");
gl.deleteTexture(tex);
}
function generateMipmap_widthHeightNotEqual()
{
debug("Generate mipmaps when width and height are not equal.");
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, 64, 32, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.generateMipmap(gl.TEXTURE_2D);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "GenerateMipmap should succeed.");
gl.deleteTexture(tex);
}
function generateMipmap_maxLevelLessThanFullMipmapLevel()
{
debug("Generate mipmaps when maxLevel is less than full mipmap level.");
wtu.setupUnitQuad(gl, 0, 1);
var program = wtu.setupProgram(
gl, ['vshader', 'fshader'], ['vPosition', 'texCoord0'], [0, 1]);
var colors = [0, 63, 127, 255];
var texLoc = gl.getUniformLocation(program, "tex");
gl.uniform1i(texLoc, 0);
var width = 16;
var height = 16;
canvas.width = width;
canvas.height = height;
gl.viewport(0, 0, width, height);
var srgbTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, srgbTex);
wtu.fillTexture(gl, srgbTex, width, height, colors, 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.SRGB8_ALPHA8);
// Set max level, check if the max level mipmap is generated.
var max_level = 3;
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, max_level);
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST);
width >>= max_level;
height >>= max_level;
canvas.width = width;
canvas.height = height;
gl.viewport(0, 0, width, height);
gl.bindTexture(gl.TEXTURE_2D, srgbTex);
wtu.clearAndDrawUnitQuad(gl);
var reference = wtu.sRGBToLinear(colors);
var msg;
wtu.checkCanvasRect(gl, 0, 0, width, height, reference, msg, [1,1,1,1]);
gl.deleteTexture(srgbTex);
}
generateMipmap();
generateMipmap_immutableTexture();
generateMipmap_widthHeightNotEqual();
generateMipmap_maxLevelLessThanFullMipmapLevel();
var successfullyParsed = true;
</script>
<script src="../../../js/js-test-post.js"></script>
</body>
</html>