Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: win10_2009 OR win11_2009 OR os == 'mac' && os_version == '11.20' && arch == 'aarch64'
- Manifest: dom/canvas/test/webgl-mochitest/mochitest.toml
<!DOCTYPE HTML>
<html>
<head>
<meta charset='UTF-8'>
<script src='/tests/SimpleTest/SimpleTest.js'></script>
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
</head>
<body>
<script>
var RED = [1, 0, 0, 1];
var GREEN = [0, 1, 0, 1];
var BLUE = [0, 0, 1, 1];
var WHITE = [1, 1, 1, 1];
var ZERO = [0, 0, 0, 0];
function DrawColors(gl) {
var fnClearToColor = function(color) {
gl.clearColor(color[0], color[1], color[2], color[3]);
gl.clear(gl.COLOR_BUFFER_BIT);
};
gl.enable(gl.SCISSOR_TEST);
// +---+
// |G W|
// |R B|
// +---+
gl.scissor(0, 0, 1, 1);
fnClearToColor(RED);
gl.scissor(1, 0, 1, 1);
fnClearToColor(BLUE);
gl.scissor(0, 1, 1, 1);
fnClearToColor(GREEN);
gl.scissor(1, 1, 1, 1);
fnClearToColor(WHITE);
}
function ClearBufferPair(gl, byteCount) {
// Using `null` here clears to zero according to WebGL.
gl.bufferData(gl.PIXEL_PACK_BUFFER, byteCount, gl.STREAM_READ);
var arr = new Uint8Array(byteCount);
return arr;
}
function ColorToString(color, offset=0) {
var arr = [ color[offset+0],
color[offset+1],
color[offset+2],
color[offset+3] ];
return '[' + arr.join(', ') + ']';
}
function TestIsUNormColor(refColor, testData, offset) {
if (testData.length < offset + 4) {
ok(false, 'testData not long enough.');
}
var refUNormColor = [
(refColor[0] * 255) | 0,
(refColor[1] * 255) | 0,
(refColor[2] * 255) | 0,
(refColor[3] * 255) | 0,
];
var refStr = ColorToString(refUNormColor);
var testStr = ColorToString(testData, offset);
ok(testStr == refStr, 'Expected ' + refStr + ', was ' + testStr + '.');
}
function section(text) {
ok(true, '');
ok(true, 'Section: ' + text);
}
function EnsureNoError(gl) {
var glErr = gl.getError();
while (gl.getError()) {}
if (!glErr)
return;
var extraInfo = '';
var err = new Error();
var stackStr = err.stack;
if (stackStr !== undefined) {
var stackArr = stackStr.split('\n');
stackStr = stackArr[1]; // First one after present scope.
extraInfo = ': ' + stackStr;
}
ok(false, 'Unexpected GL error: 0x' + glErr.toString(16) + extraInfo);
}
function TestError(gl, refErrVal, str='') {
if (str == '') {
str = 'gl.getError()';
} else {
str = str + ': gl.getError()';
}
var err = gl.getError();
while (gl.getError()) {}
ShouldBe(err.toString(16), refErrVal.toString(16), str);
}
function ShouldBe(val, ref, str='') {
if (str != '') {
str += ': ';
}
ok(val == ref, str + 'Should be `' + ref + '`, was `' + val + '`.');
}
var gl;
function Test() {
var canvas = document.createElement('canvas');
canvas.width = 2;
canvas.height = 2;
canvas.style = 'width: 256px; height: 256px; border: 1px solid black;';
document.body.appendChild(canvas);
var attribs = {
antialias: false,
alpha: false,
};
gl = canvas.getContext('webgl2', attribs);
if (!gl) {
todo(false, 'WebGL 2 not present, skipping.');
return;
}
////////
TestIsUNormColor(RED, new Uint8Array([255, 0, 0, 255]), 0);
////////
gl.clearColor(RED[0], RED[1], RED[2], RED[3]);
gl.clear(gl.COLOR_BUFFER_BIT);
var data = new Uint8Array(16);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
console.log(JSON.stringify(data));
TestIsUNormColor(RED, data, 0);
////////
DrawColors(gl);
////////
EnsureNoError(gl);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, 0);
TestError(gl, gl.INVALID_OPERATION);
var data = new Uint8Array(16);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
EnsureNoError(gl);
TestIsUNormColor(RED, data, 0);
TestIsUNormColor(BLUE, data, 4);
TestIsUNormColor(GREEN, data, 8);
TestIsUNormColor(WHITE, data, 12);
////////
var a = gl.createBuffer();
gl.bindBuffer(gl.PIXEL_PACK_BUFFER, a);
EnsureNoError(gl);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, data);
TestError(gl, gl.INVALID_OPERATION);
////////
// Basic
section('Basic readback');
data = ClearBufferPair(gl, 16);
EnsureNoError(gl);
gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, 0);
EnsureNoError(gl);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data);
EnsureNoError(gl);
TestIsUNormColor(RED, data, 0);
TestIsUNormColor(BLUE, data, 4);
TestIsUNormColor(GREEN, data, 8);
TestIsUNormColor(WHITE, data, 12);
section('Subrect readback');
data = ClearBufferPair(gl, 8);
gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 0);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data);
EnsureNoError(gl);
TestIsUNormColor(WHITE, data, 0);
TestIsUNormColor(ZERO, data, 4);
section('ReadPixels offset:4');
data = ClearBufferPair(gl, 16);
gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 4);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data);
EnsureNoError(gl);
TestIsUNormColor(ZERO, data, 0);
TestIsUNormColor(WHITE, data, 4);
TestIsUNormColor(ZERO, data, 8);
TestIsUNormColor(ZERO, data, 12);
section('ReadPixels offset:5');
gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 5);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, data);
EnsureNoError(gl);
TestIsUNormColor(ZERO, data, 0);
TestIsUNormColor(WHITE, data, 4); // Should remain from previous read.
TestIsUNormColor(WHITE, data, 5);
TestIsUNormColor(ZERO, data, 9);
TestIsUNormColor(ZERO, data, 12);
section('GetBufferSubData src too small');
data = ClearBufferPair(gl, 16);
EnsureNoError(gl);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 1, data);
TestError(gl, gl.INVALID_VALUE);
TestIsUNormColor(ZERO, data, 0);
TestIsUNormColor(ZERO, data, 4);
TestIsUNormColor(ZERO, data, 8);
TestIsUNormColor(ZERO, data, 12);
section('GetBufferSubData offset:1');
data = new Uint8Array(15);
gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, 8);
gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 1, data);
EnsureNoError(gl);
TestIsUNormColor(ZERO, data, 0);
TestIsUNormColor(ZERO, data, 3);
TestIsUNormColor(WHITE, data, 7);
TestIsUNormColor(ZERO, data, 11);
//////////////////////////////////////
section('Test packing state');
EnsureNoError(gl);
function TestPackState(enumStr, initialVal, changedVal) {
var enumVal = gl[enumStr];
ShouldBe(gl.getParameter(enumVal), initialVal, 'Initial ' + enumStr);
gl.pixelStorei(enumVal, changedVal);
ShouldBe(gl.getParameter(enumVal), changedVal, 'Changed ' + enumStr);
gl.pixelStorei(enumVal, initialVal);
ShouldBe(gl.getParameter(enumVal), initialVal, 'Reverted ' + enumStr);
EnsureNoError(gl);
}
TestPackState('PACK_ALIGNMENT', 4, 1);
TestPackState('PACK_ROW_LENGTH', 0, 16);
TestPackState('PACK_SKIP_PIXELS', 0, 3);
TestPackState('PACK_SKIP_ROWS', 0, 3);
}
function RunTest() {
Test();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
try {
var prefArrArr = [
['webgl.force-enabled', true],
['webgl.disable-angle', true],
];
var prefEnv = {'set': prefArrArr};
SpecialPowers.pushPrefEnv(prefEnv, RunTest);
} catch (e) {
todo(false, 'No SpecialPowers, but trying anyway...');
RunTest();
}
</script>
</body>
</html>