<!DOCTYPE html>
<html>
<!--
Creates 8 WebGL canvases with the cross-product of WebGL version, anti-aliasing,
and premultiplied alpha. Uses drawingBufferStorage to ensure these canvases are
sRGB encoded. Draws a color that will match rgba(255, 128, 0, 0.5);
The result should be a rectangle of a solid color.
If a sub-test can't run (e.g, because WebGL, WebGL 2, or EXT_sRGB is not
present), then that sub-test will report a passing result (by setting its
background color to the expected color).
-->
<head>
<script>
function sendResult(status) {
if (window.domAutomationController) {
window.domAutomationController.send(status);
} else {
console.log(status);
}
}
var g_swapsBeforeAck = 15;
function waitForFinish() {
if (g_swapsBeforeAck == 0) {
sendResult("SUCCESS");
} else {
g_swapsBeforeAck--;
window.requestAnimationFrame(waitForFinish);
}
}
function drawQuad(elementId, contextType, contextOptions, color, expected) {
let testSkipColor = 'rgba(255, 128, 0, 0.5019607843137255)';
let element = document.getElementById(elementId);
let gl = element.getContext(contextType, contextOptions);
if (!gl) {
sendResult("FAILURE", "Failed to create WebGL context");
return;
}
let format = null;
if (contextType == 'webgl') {
let ext = gl.getExtension('EXT_sRGB');
if (!ext) {
sendResult("FAILURE", "EXT_sRGB not present");
return;
}
format = ext.SRGB8_ALPHA8_EXT;
} else
if (contextType == 'webgl2') {
format = gl.SRGB8_ALPHA8;
}
gl.drawingBufferStorage(format,
gl.drawingBufferWidth,
gl.drawingBufferHeight);
// Create the program to draw a point sprite.
let program = null;
{
let compileShader = function(gl, vertCode, fragCode) {
let vertShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertShader, vertCode);
gl.compileShader(vertShader);
if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS))
throw new Error(gl.getShaderInfoLog(vertShader));
let fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragShader, fragCode);
gl.compileShader(fragShader);
if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS))
throw new Error(gl.getShaderInfoLog(fragShader));
let shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertShader);
gl.attachShader(shaderProgram, fragShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
throw new Error(gl.getProgramInfoLog(program));
return shaderProgram;
}
let vs = `attribute vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}`;
let fs = `precision mediump float;
uniform vec4 color;
void main() {
gl_FragColor = color;
}`;
program = compileShader(gl, vs, fs);
}
gl.useProgram(program);
// Draw using that program.
{
let vertices = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertices);
gl.bufferData(gl.ARRAY_BUFFER,
new Float32Array([-1,-1, 1,-1, 1,1, -1,1]),
gl.STATIC_DRAW);
let indices = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array([0,1,2, 0,2,3]),
gl.STATIC_DRAW);
let positionLocation = gl.getAttribLocation(program, 'position');
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLocation);
gl.uniform4fv(gl.getUniformLocation(program, 'color'), color);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
}
// Ensure that we can read back the values and get the expected results.
let pixels = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
for (let c = 0; c < 4; ++c) {
const epsilon = 6;
if (Math.abs(pixels[c] - expected[c]) > epsilon) {
const failureText = "Incorrect result from readPixels." +
" Expected:" + expected +
" Actual:" + pixels;
sendResult("FAILURE", failureText);
return;
}
}
}
function main() {
let srgbToLinear = function(x) {
if (x < 0.0)
return 0.0;
if (x < 0.04045)
return x / 12.92;
if (x < 1.0) {
return Math.pow((x + 0.055)/1.055, 2.4);
}
return 1.0;
}
let colorPremul = new Float32Array([
srgbToLinear(128/255), srgbToLinear(64/255), 0.0, 128/255]);
let expectedPremul = new Uint8Array([
128, 64, 0,128]);
let colorUnmul = new Float32Array([
1.0, srgbToLinear(128/255), 0.0, 128/255]);
let expectedUnmul = new Uint8Array([
255, 128, 0, 128]);
drawQuad('c0', 'webgl', {premultipliedAlpha: true, antialias:false},
colorPremul, expectedPremul);
drawQuad('c1', 'webgl', {premultipliedAlpha: true, antialias:true},
colorPremul, expectedPremul);
drawQuad('c2', 'webgl', {premultipliedAlpha: false, antialias:false},
colorUnmul, expectedUnmul);
drawQuad('c3', 'webgl', {premultipliedAlpha: false, antialias:true},
colorUnmul, expectedUnmul);
drawQuad('c4', 'webgl2', {premultipliedAlpha: true, antialias:false},
colorPremul, expectedPremul);
drawQuad('c5', 'webgl2', {premultipliedAlpha: true, antialias:true},
colorPremul, expectedPremul);
drawQuad('c6', 'webgl2', {premultipliedAlpha: false, antialias:false},
colorUnmul, expectedUnmul);
drawQuad('c7', 'webgl2', {premultipliedAlpha: false, antialias:true},
colorUnmul, expectedUnmul);
waitForFinish();
}
</script>
</head>
<body onload='main()'>
<p style='width:160px; height:32px;
background-color:rgba(255, 128, 0, 0.5019607843137255);
position:absolute; left:8px; top: 8px;'></p>
<p style='width:160px; height:32px;
background-color:rgba(255, 128, 0, 0.5019607843137255);
position:absolute; left:8px; top:72px;'></p>
<canvas id='c0' width='20' height='32'
style='position:absolute; left: 8px; top:56px;'></canvas>
<canvas id='c1' width='20' height='32'
style='position:absolute; left: 28px; top:56px;'></canvas>
<canvas id='c2' width='20' height='32'
style='position:absolute; left: 48px; top:56px;'></canvas>
<canvas id='c3' width='20' height='32'
style='position:absolute; left: 68px; top:56px;'></canvas>
<canvas id='c4' width='20' height='32'
style='position:absolute; left: 88px; top:56px;'></canvas>
<canvas id='c5' width='20' height='32'
style='position:absolute; left:108px; top:56px;'></canvas>
<canvas id='c6' width='20' height='32'
style='position:absolute; left:128px; top:56px;'></canvas>
<canvas id='c7' width='20' height='32'
style='position:absolute; left:148px; top:56px;'></canvas>
</body>
</html>