<!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>