diff options
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/js/tests')
41 files changed, 9136 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/clipping-wide-points.js b/dom/canvas/test/webgl-conf/checkout/js/tests/clipping-wide-points.js new file mode 100644 index 000000000..fd86bf5fd --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/clipping-wide-points.js @@ -0,0 +1,109 @@ +/* +** 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. +*/ + +'use strict'; +description("This test ensures clipping works with wide points whose centers are out of the viewport"); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("testbed", undefined, contextVersion); + +var pointSize; + +function setupProgram() { + var vs = "attribute vec4 pos;" + + "uniform float pointSize; " + + "void main() {" + + " gl_PointSize = pointSize;" + + " gl_Position = pos;" + + "}"; + var fs = "precision mediump float;" + + "void main() {" + + " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);" + + "}"; + var program = wtu.setupProgram(gl, [vs, fs], ['pos']); + if (program) { + var loc = gl.getUniformLocation(program, 'pointSize'); + gl.uniform1f(loc, pointSize); + gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors after setting up program"); + } + return program; +} + +function runOneTestCase(vertex) { + debug(""); + debug("testing point at (" + vertex[0] + ", " + vertex[1] + ", " + vertex[2] + ")"); + var data = new Float32Array(vertex); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, data); + + gl.clear(gl.COLOR_BUFFER_BIT); + gl.drawArrays(gl.POINTS, 0, 1); + wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 255, 0]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors after running one test case"); +} + +function runTests() { + if (!gl) { + testFailed("context does not exist"); + return; + } + + var range = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE); + if (range[1] < 2.0) { + testPassed("ALIASDED_POINT_SIZE_RANGE less than 2"); + return; + } + pointSize = 2.0; + + var data = new Float32Array(4); + var buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW); + + var program = setupProgram(); + if (!program) { + testFailed("fail to set up program"); + return; + } + + gl.disable(gl.BLEND); + gl.disable(gl.DITHER); + gl.disable(gl.DEPTH_TEST); + + gl.clearColor(1.0, 0.0, 0.0, 1.0); + + var vertices = [ + [ 0.99, 0.5, 0.0, 1.0 ], + [ 1.01, 0.5, 0.0, 1.0 ], + [ 0.5, 0.99, 0.0, 1.0 ], + [ 0.5, 1.01, 0.0, 1.0 ], + ]; + for (var idx = 0; idx < vertices.length; ++idx) { + runOneTestCase(vertices[idx]); + } +} + +runTests(); +debug(""); +var successfullyParsed = true; diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/compound-assignment-type-combination.js b/dom/canvas/test/webgl-conf/checkout/js/tests/compound-assignment-type-combination.js new file mode 100644 index 000000000..d824f3194 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/compound-assignment-type-combination.js @@ -0,0 +1,150 @@ +/* +** Copyright (c) 2014 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. +*/ + +'use strict'; + +// ESSL 1.00 spec section 5.8 (also ESSL 3.00 spec section 5.8): +// "The l-value and the expression must satisfy the semantic requirements of both op and equals (=)" +// In the semantic requirements of assignment (=): +// "The lvalue-expression and rvalue-expression must have the same type" + +var runTest = function(contextVersion) { + var vertexTemplateESSL1 = [ + 'precision mediump float;', + + 'uniform $(rtype) ur;', + 'uniform $(ltype) ul;', + + 'void main() {', + ' $(ltype) a = ul;', + ' a $(op) ur;', + ' gl_Position = vec4(float(a$(ltypeToScalar)));', + '}' + ].join('\n'); + + var vertexTemplateESSL3 = [ + '#version 300 es', + vertexTemplateESSL1 + ].join('\n'); + + var fragmentTemplateESSL1 = [ + 'precision mediump float;', + + 'uniform $(rtype) ur;', + 'uniform $(ltype) ul;', + + 'void main() {', + ' $(ltype) a = ul;', + ' a $(op) ur;', + ' gl_FragColor = vec4(float(a$(ltypeToScalar)));', + '}' + ].join('\n'); + + var fragmentTemplateESSL3 = [ + '#version 300 es', + 'out mediump vec4 my_FragColor;', + fragmentTemplateESSL1 + ].join('\n').replace('gl_FragColor', 'my_FragColor'); + + var isNonSquareMatrix = function(typeStr) { + return typeStr.substring(0, 3) == 'mat' && + typeStr.length > 5 && + typeStr[3] != typeStr[5]; + } + + var vsTemplate = contextVersion < 2 ? vertexTemplateESSL1 : vertexTemplateESSL3; + var fsTemplate = contextVersion < 2 ? fragmentTemplateESSL1 : fragmentTemplateESSL3; + + var wtu = WebGLTestUtils; + + var tests = []; + + var baseTypes = ['float', 'int']; + var vecTypes = [['vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4'], ['ivec2', 'ivec3', 'ivec4']]; + if (contextVersion >= 2) { + vecTypes[0] = ['vec2', 'vec3', 'vec4', 'mat2x2', 'mat3x3', 'mat4x4', 'mat2x3', 'mat2x4', 'mat3x2', 'mat3x4', 'mat4x2', 'mat4x3']; + } + var ops = ['+=', '-=', '*=', '/=']; + + var fs, vs; + for (var k = 0; k < ops.length; ++k) { + var op = ops[k]; + for (var i = 0; i < baseTypes.length; ++i) { + var baseType = baseTypes[i]; + for (var j = 0; j < vecTypes[i].length; ++j) { + var vecType = vecTypes[i][j]; + var vecTypeToScalar = vecType.substring(0, 3) == 'mat' ? '[0].x' : '.x'; + + var pushTest = function(ltype, rtype, ltypeToScalar, expectSuccess) { + vs = wtu.replaceParams(vsTemplate, {ltype: ltype, rtype: rtype, ltypeToScalar: ltypeToScalar, op: op}); + fs = wtu.replaceParams(fsTemplate, {ltype: ltype, rtype: rtype, ltypeToScalar: ltypeToScalar, op: op}); + tests.push({ + vShaderSource: vs, + vShaderSuccess: expectSuccess, + linkSuccess: expectSuccess, + passMsg: ltype + " " + op + " " + rtype + " in a vertex shader should " + (expectSuccess ? "succeed." : "fail.") + }); + tests.push({ + fShaderSource: fs, + fShaderSuccess: expectSuccess, + linkSuccess: expectSuccess, + passMsg: ltype + " " + op + " " + rtype + " in a fragment shader should " + (expectSuccess ? "succeed." : "fail.") + }); + } + + // "scalar op= vector" is not okay, since the result of op is a vector, + // which can't be assigned to a scalar. + pushTest(baseType, vecType, '', false); + + if (j > 0) { + var vecType2 = vecTypes[i][j - 1]; + // "vector1 op= vector2" is not okay when vector1 and vector2 have + // non-matching dimensions. + pushTest(vecType, vecType2, vecTypeToScalar, false); + } + + // "vector op= scalar" is okay. + pushTest(vecType, baseType, vecTypeToScalar, true); + + // vecX *= matX is okay (effectively, this treats vector as a row vector). + if (vecType.substring(0, 3) == 'vec' && op == '*=') { + pushTest(vecType, 'mat' + vecType[3], vecTypeToScalar, true); + } + + if (op != '*=' || !isNonSquareMatrix(vecType)) { + // "vector1 op= vector2" is okay when vector1 and vector2 have the same + // type (does a component-wise operation or matrix multiplication). + pushTest(vecType, vecType, vecTypeToScalar, true); + } else { + // non-square matrices can only be compound multiplied with a square matrix. + pushTest(vecType, vecType, vecTypeToScalar, false); + pushTest(vecType, 'mat' + vecType[3], vecTypeToScalar, true); + } + } + } + } + + GLSLConformanceTester.runTests(tests, contextVersion); +} + +var successfullyParsed = true; diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/gl-enum-tests.js b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-enum-tests.js new file mode 100644 index 000000000..3a17f09b2 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-enum-tests.js @@ -0,0 +1,140 @@ +/* +** Copyright (c) 2015 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. +*/ + +// This test relies on the surrounding web page defining a variable +// "contextVersion" which indicates what version of WebGL it's running +// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc. + +"use strict"; +description("This test ensures various WebGL functions fail when passed invalid OpenGL ES enums."); + +debug(""); +debug("Canvas.getContext"); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("canvas", undefined, contextVersion); +if (!gl) { + testFailed("context does not exist"); +} else { + testPassed("context exists"); + + debug(""); + debug("Checking gl enums."); + + var buffer = new ArrayBuffer(2); + var buf = new Uint16Array(buffer); + var tex = gl.createTexture(); + var program = wtu.createProgram(gl, wtu.loadStandardVertexShader(gl), wtu.loadStandardFragmentShader(gl)); + gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + var tests = [ + "gl.disable(desktopGL['CLIP_PLANE0'])", + "gl.disable(desktopGL['POINT_SPRITE'])", + "gl.getBufferParameter(gl.ARRAY_BUFFER, desktopGL['PIXEL_PACK_BUFFER'])", + "gl.hint(desktopGL['PERSPECTIVE_CORRECTION_HINT'], gl.FASTEST)", + "gl.isEnabled(desktopGL['CLIP_PLANE0'])", + "gl.isEnabled(desktopGL['POINT_SPRITE'])", + "gl.pixelStorei(desktopGL['PACK_SWAP_BYTES'], 1)", + "gl.getParameter(desktopGL['NUM_COMPRESSED_TEXTURE_FORMATS'])", + "gl.getParameter(desktopGL['EXTENSIONS'])", + "gl.getParameter(desktopGL['SHADER_COMPILER'])", + "gl.getParameter(desktopGL['SHADER_BINARY_FORMATS'])", + "gl.getParameter(desktopGL['NUM_SHADER_BINARY_FORMATS'])", + ]; + + if (contextVersion < 2) { + tests = tests.concat([ + "gl.blendEquation(desktopGL['MIN'])", + "gl.blendEquation(desktopGL['MAX'])", + "gl.blendEquationSeparate(desktopGL['MIN'], gl.FUNC_ADD)", + "gl.blendEquationSeparate(desktopGL['MAX'], gl.FUNC_ADD)", + "gl.blendEquationSeparate(gl.FUNC_ADD, desktopGL['MIN'])", + "gl.blendEquationSeparate(gl.FUNC_ADD, desktopGL['MAX'])", + "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['STREAM_READ'])", + "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['STREAM_COPY'])", + "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['STATIC_READ'])", + "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['STATIC_COPY'])", + "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['DYNAMIC_READ'])", + "gl.bufferData(gl.ARRAY_BUFFER, 16, desktopGL['DYNAMIC_COPY'])", + "gl.bindTexture(desktopGL['TEXTURE_2D_ARRAY'], tex)", + "gl.bindTexture(desktopGL['TEXTURE_3D'], tex)", + ]); + } else { + tests = tests.concat([ + "gl.bindTexture(desktopGL['TEXTURE_RECTANGLE_EXT'], tex)", + "gl.enable(desktopGL['PRIMITIVE_RESTART_FIXED_INDEX'])", + "gl.getActiveUniforms(program, [0], desktopGL['UNIFORM_NAME_LENGTH'])", + "gl.getProgramParameter(program, desktopGL['ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH'])", + "gl.getProgramParameter(program, desktopGL['TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH'])", + "gl.getProgramParameter(program, desktopGL['PROGRAM_BINARY_RETRIEVABLE_HINT'])", + "gl.getProgramParameter(program, desktopGL['PROGRAM_BINARY_LENGTH'])", + "gl.getParameter(program, desktopGL['NUM_PROGRAM_BINARY_FORMATS'])", + ]); + } + + for (var ii = 0; ii < tests.length; ++ii) { + TestEval(tests[ii]); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, tests[ii] + " should return INVALID_ENUM."); + } + + gl.bindTexture(gl.TEXTURE_2D, tex); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + tests = [ + "gl.getTexParameter(gl.TEXTURE_2D, desktopGL['GENERATE_MIPMAP'])", + "gl.texParameteri(gl.TEXTURE_2D, desktopGL['GENERATE_MIPMAP'], 1)", + "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, desktopGL['CLAMP_TO_BORDER'])", + ]; + + if (contextVersion < 2) { + tests = tests.concat([ + "gl.texParameteri(desktopGL['TEXTURE_2D_ARRAY'], gl.TEXTURE_MAG_FILTER, gl.NEAREST)", + "gl.texParameteri(desktopGL['TEXTURE_3D'], gl.TEXTURE_MAG_FILTER, gl.NEAREST)", + ]); + } else { + tests = tests.concat([ + "gl.texParameteri(desktopGL['TEXTURE_2D'], desktopGL['TEXTURE_SWIZZLE_R_EXT'], gl.RED)", + "gl.texParameteri(desktopGL['TEXTURE_2D'], desktopGL['TEXTURE_SWIZZLE_G_EXT'], gl.RED)", + "gl.texParameteri(desktopGL['TEXTURE_2D'], desktopGL['TEXTURE_SWIZZLE_B_EXT'], gl.RED)", + "gl.texParameteri(desktopGL['TEXTURE_2D'], desktopGL['TEXTURE_SWIZZLE_A_EXT'], gl.RED)", + "gl.texParameteri(desktopGL['TEXTURE_2D'], gl.TEXTURE_WRAP_R, desktopGL['CLAMP_TO_BORDER'])", + ]); + } + + for (var ii = 0; ii < tests.length; ++ii) { + TestEval(tests[ii]); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, tests[ii] + " should return INVALID_ENUM."); + } + if (contextVersion >= 2) { + var uniformBlockProgram = wtu.loadUniformBlockProgram(gl); + gl.linkProgram(uniformBlockProgram); + shouldBe('gl.getProgramParameter(uniformBlockProgram, gl.LINK_STATUS)', 'true'); + shouldBe('gl.getError()', 'gl.NO_ERROR'); + gl.getActiveUniformBlockParameter(uniformBlockProgram, 0, desktopGL['UNIFORM_BLOCK_NAME_LENGTH']); + shouldBe('gl.getError()', 'gl.INVALID_ENUM'); + } +} + +debug(""); +var successfullyParsed = true; diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/gl-get-tex-parameter.js b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-get-tex-parameter.js new file mode 100644 index 000000000..db38fb05c --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-get-tex-parameter.js @@ -0,0 +1,200 @@ +/* +** Copyright (c) 2015 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. +*/ + +// This test relies on the surrounding web page defining a variable +// "contextVersion" which indicates what version of WebGL it's running +// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc. + +"use strict"; +description(); +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("example", undefined, contextVersion); + +// NOTE: We explicitly do this in a funky order +// to hopefully find subtle bugs. + +var targets = [ + 'TEXTURE_2D', + 'TEXTURE_2D', + 'TEXTURE_CUBE_MAP', + 'TEXTURE_CUBE_MAP' +]; + +if (contextVersion > 1) { + targets = targets.concat([ + 'TEXTURE_2D_ARRAY', + 'TEXTURE_2D_ARRAY', + 'TEXTURE_3D', + 'TEXTURE_3D' + ]); +} + +// Create textures on different active textures. +for (var ii = 0; ii < targets.length; ++ii) { + var target = targets[ii]; + var tex = gl.createTexture(); + gl.activeTexture(gl.TEXTURE0 + ii); + gl.bindTexture(gl[target], tex); +} + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + +var states = [ + { state: 'TEXTURE_WRAP_S', default: 'REPEAT', value1: 'CLAMP_TO_EDGE', value2: 'REPEAT' }, + { state: 'TEXTURE_WRAP_T', default: 'REPEAT', value1: 'MIRRORED_REPEAT', value2: 'REPEAT' }, + { state: 'TEXTURE_MAG_FILTER', default: 'LINEAR', value1: 'NEAREST', value2: 'LINEAR' }, + { state: 'TEXTURE_MIN_FILTER', default: 'NEAREST_MIPMAP_LINEAR', value1: 'LINEAR_MIPMAP_LINEAR', value2: 'NEAREST' } +]; + +if (contextVersion > 1) { + states = states.concat([ + { state: 'TEXTURE_WRAP_R', default: 'REPEAT', value1: 'CLAMP_TO_EDGE', value2: 'MIRRORED_REPEAT' }, + { state: 'TEXTURE_COMPARE_FUNC', default: 'LEQUAL', value1: 'GREATER', value2: 'LESS' }, + { state: 'TEXTURE_COMPARE_MODE', default: 'NONE', value1: 'COMPARE_REF_TO_TEXTURE', value2: 'NONE' }, + { state: 'TEXTURE_BASE_LEVEL', default: 0, value1: 100, value2: 99 }, + { state: 'TEXTURE_MAX_LEVEL', default: 1000, value1: 800, value2: 300 }, + { state: 'TEXTURE_MIN_LOD', default: -1000.0, value1: -500.0, value2: -999.0 }, + { state: 'TEXTURE_MAX_LOD', default: 1000.0, value1: 500.0, value2: 999.0 }, + // Note: For TEXTURE_IMMUTABLE_LEVELS and TEXTURE_IMMUTABLE_FORMAT, + // these two pname are used by getTexParameter API only, not available in texParameter[fi] in specifications. + // Thus, these two states store default value only. + { state: 'TEXTURE_IMMUTABLE_LEVELS', default: 0, }, + { state: 'TEXTURE_IMMUTABLE_FORMAT', default: false, } + ]); +} + +function getStateInfoValue(stateInfo, item, method) { + switch (stateInfo.state) { + case 'TEXTURE_WRAP_R': + case 'TEXTURE_WRAP_S': + case 'TEXTURE_WRAP_T': + case 'TEXTURE_MAG_FILTER': + case 'TEXTURE_MIN_FILTER': + case 'TEXTURE_COMPARE_FUNC': + case 'TEXTURE_COMPARE_MODE': + if (method === 'Get') { + return 'gl["' + stateInfo[item] + '"]'; + } else if (method === 'Set') { + return gl[stateInfo[item]]; + } + break; + case 'TEXTURE_BASE_LEVEL': + case 'TEXTURE_MAX_LEVEL': + case 'TEXTURE_MIN_LOD': + case 'TEXTURE_MAX_LOD': + if (method === 'Get') { + return '' + stateInfo[item]; + } else if (method === 'Set') { + return stateInfo[item]; + } + break; + case 'TEXTURE_IMMUTABLE_LEVELS': + case 'TEXTURE_IMMUTABLE_FORMAT': + // Return default value only. + return '' + stateInfo.default; + default: + wtu.error("Not reached!"); + return null; + break; + } +} + +function applyStates(fn) { + for (var ss = 0; ss < states.length; ++ss) { + var stateInfo = states[ss]; + for (var ii = 0; ii < targets.length; ++ii) { + var target = targets[ii]; + gl.activeTexture(gl.TEXTURE0 + ii); + fn(target, stateInfo); + } + } +} + +// test the default state. +applyStates(function(target, stateInfo) { + var a = 'gl.getTexParameter(gl["' + target + '"], gl["' + stateInfo.state + '"])'; + var b = getStateInfoValue(stateInfo, 'default', 'Get'); + shouldBe(a, b); +}); + +// test new state +applyStates(function(target, stateInfo) { + switch (stateInfo.state) { + case 'TEXTURE_IMMUTABLE_FORMAT': + case 'TEXTURE_IMMUTABLE_LEVELS': + // Skip these two pname for texParameterf[fi]. + break; + case 'TEXTURE_MIN_LOD': + case 'TEXTURE_MAX_LOD': + gl.texParameterf(gl[target], gl[stateInfo.state], getStateInfoValue(stateInfo, 'value1', 'Set')); + break; + default: + gl.texParameteri(gl[target], gl[stateInfo.state], getStateInfoValue(stateInfo, 'value1', 'Set')); + break; + } +}); + +applyStates(function(target, stateInfo) { + var a = 'gl.getTexParameter(gl["' + target + '"], gl["' + stateInfo.state + '"])'; + var b = getStateInfoValue(stateInfo, 'value1', 'Get'); + shouldBe(a, b); +}); + +// test different states on each target. +function getItem(count) { + return (count % 2) ? 'value2' : 'value1'; +} + +applyStates(function() { + var count = 0; + return function(target, stateInfo) { + switch (stateInfo.state) { + case 'TEXTURE_IMMUTABLE_FORMAT': + case 'TEXTURE_IMMUTABLE_LEVELS': + // Skip these two pname for texParameterf[fi]. + break; + case 'TEXTURE_MIN_LOD': + case 'TEXTURE_MAX_LOD': + gl.texParameterf(gl[target], gl[stateInfo.state], getStateInfoValue(stateInfo, getItem(count), 'Set')); + break; + default: + gl.texParameteri(gl[target], gl[stateInfo.state], getStateInfoValue(stateInfo, getItem(count), 'Set')); + break; + } + ++count; + } +}()); + +applyStates(function() { + var count = 0; + return function(target, stateInfo) { + var a = 'gl.getTexParameter(gl["' + target + '"], gl["' + stateInfo.state + '"])'; + var b = getStateInfoValue(stateInfo, getItem(count), 'Get'); + shouldBe(a, b); + ++count; + }; +}()); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + +var successfullyParsed = true; diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/gl-object-get-calls.js b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-object-get-calls.js new file mode 100644 index 000000000..05e5a053d --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-object-get-calls.js @@ -0,0 +1,1092 @@ +/* +** Copyright (c) 2015 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. +*/ + +// This test relies on the surrounding web page defining a variable +// "contextVersion" which indicates what version of WebGL it's running +// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc. + +"use strict"; +var wtu = WebGLTestUtils; +description("Test of get calls against GL objects like getBufferParameter, etc."); + +var gl = wtu.create3DContext(undefined, undefined, contextVersion); + +function testInvalidArgument(funcName, argumentName, validArgumentArray, func) { + var validArguments = {}; + for (var ii = 0; ii < validArgumentArray.length; ++ii) { + validArguments[validArgumentArray[ii]] = true; + } + var success = true; + for (var ii = 0; ii < 0x10000; ++ii) { + if (!validArguments[ii]) { + var result = func(ii); + if (result !== null) { + success = false; + testFailed(funcName + " returned " + result + " instead of null for invalid " + argumentName + " enum: " + wtu.glEnumToString(gl, ii)); + break; + } + var err = gl.getError(); + if (err != gl.INVALID_ENUM) { + success = false; + testFailed(funcName + " did not generate INVALID_ENUM for invalid " + argumentName + " enum: " + wtu.glEnumToString(gl, ii)); + break; + } + } + } + if (success) { + testPassed(funcName + " correctly handled invalid " + argumentName + " enums"); + } +} + +debug(""); +debug("test getBufferParameter"); +// Test getBufferParameter +var bufferTypes = [gl.ARRAY_BUFFER, gl.ELEMENT_ARRAY_BUFFER]; +if (contextVersion > 1) { + bufferTypes = bufferTypes.concat([gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, gl.PIXEL_PACK_BUFFER, gl.PIXEL_UNPACK_BUFFER, gl.TRANSFORM_FEEDBACK_BUFFER, gl.UNIFORM_BUFFER]); +} +for (var bb = 0; bb < bufferTypes.length; ++bb) { + var bufferType = bufferTypes[bb]; + var buffer = gl.createBuffer(); + gl.bindBuffer(bufferType, buffer); + gl.bufferData(bufferType, 16, gl.DYNAMIC_DRAW); + var expression1 = "gl.getBufferParameter(gl." + wtu.glEnumToString(gl, bufferType) + ", gl.BUFFER_SIZE)"; + var expression2 = "gl.getBufferParameter(gl." + wtu.glEnumToString(gl, bufferType) + ", gl.BUFFER_USAGE)"; + shouldBe(expression1, '16'); + shouldBe(expression2, 'gl.DYNAMIC_DRAW'); + testInvalidArgument("getBufferParameter", "parameter", [gl.BUFFER_SIZE, gl.BUFFER_USAGE], function(bufferType) { + return function(parameter) { + return gl.getBufferParameter(bufferType, parameter); + }; + }(bufferType)); + gl.bindBuffer(bufferType, null); +} +testInvalidArgument( + "getBufferParameter", + "target", + bufferTypes, + function(target) { + return gl.getBufferParameter(target, gl.BUFFER_SIZE); + } +); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +var testCases = [ + { contextStencil: true}, + { contextStencil: false} +]; + +for (var run = 0; run < testCases.length; ++run) { + debug(""); + debug("Test getFramebufferAttachmentParameter with stencil " + testCases[run].contextStencil); + + if (testCases[run].contextStencil) { + gl = wtu.create3DContext(null, {stencil: true}, contextVersion); + } else { + gl = wtu.create3DContext(null, {stencil: false}, contextVersion); + } + + var texture = gl.createTexture(); + var anotherTexture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, + new Uint8Array([ + 0, 0, 0, 255, + 255, 255, 255, 255, + 255, 255, 255, 255, + 0, 0, 0, 255])); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.bindTexture(gl.TEXTURE_2D, null); + var framebuffer = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + var colorAttachmentsNum = 1; + if (contextVersion > 1) { + gl.bindTexture(gl.TEXTURE_2D, anotherTexture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, + new Uint8Array([ + 0, 0, 0, 255, + 255, 255, 255, 255, + 255, 255, 255, 255, + 0, 0, 0, 255])); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.bindTexture(gl.TEXTURE_2D, null); + colorAttachmentsNum = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + colorAttachmentsNum - 1, gl.TEXTURE_2D, anotherTexture, 0); + } + var renderbuffer = gl.createRenderbuffer(); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + if (contextVersion == 1) + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 2, 2); + else + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, 2, 2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer); + if (contextVersion > 1) + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer); + shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE'); + // The for loop tests two color attachments for WebGL 2: the first one (gl.COLOR_ATTACHMENT0) + // and the last one (gl.COLOR_ATTACHMENT0 + gl.MAX_COLOR_ATTACHMENTS - 1). + for (var ii = 0; ii < colorAttachmentsNum; ii += (colorAttachmentsNum > 1 ? colorAttachmentsNum - 1 : 1)) { + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.TEXTURE'); + if (ii == 0) + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'texture'); + else + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'anotherTexture'); + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL)', '0'); + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE)', '0'); + if (contextVersion > 1) { + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_RED_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_GREEN_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)'); + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + ' + ii + ', gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER)', '0'); + } + } + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.RENDERBUFFER'); + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'renderbuffer'); + if (contextVersion > 1) { + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.RENDERBUFFER'); + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'renderbuffer'); + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.RENDERBUFFER'); + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'renderbuffer'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)'); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)'); + } + var validParametersForFBAttachment = + [ gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, + gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE + ]; + if (contextVersion > 1) { + validParametersForFBAttachment = validParametersForFBAttachment.concat([ + gl.FRAMEBUFFER_ATTACHMENT_RED_SIZE, + gl.FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, + gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, + gl.FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, + gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, + gl.FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, + gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, + gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, + gl.FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER + ]); + } + testInvalidArgument( + "getFramebufferAttachmentParameter", + "parameter", + validParametersForFBAttachment, + function(parameter) { + return gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT, parameter); + } + ); + var validTargetsForFBAttachment = [gl.FRAMEBUFFER]; + if (contextVersion > 1) { + validTargetsForFBAttachment = validTargetsForFBAttachment.concat([gl.READ_FRAMEBUFFER, gl.DRAW_FRAMEBUFFER]); + } + testInvalidArgument( + "getFramebufferAttachmentParameter", + "target", + validTargetsForFBAttachment, + function(target) { + return gl.getFramebufferAttachmentParameter(target, gl.COLOR_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + } + ); + var validAttachmentsForFBAttachment = new Array( + gl.COLOR_ATTACHMENT0, + gl.DEPTH_ATTACHMENT, + gl.STENCIL_ATTACHMENT, + gl.DEPTH_STENCIL_ATTACHMENT + ); + if (contextVersion > 1) { + for (var ii = 1; ii < gl.getParameter(gl.MAX_COLOR_ATTACHMENTS); ++ii) { + validAttachmentsForFBAttachment[validAttachmentsForFBAttachment.length] = gl.COLOR_ATTACHMENT0 + ii; + } + } + testInvalidArgument( + "getFramebufferAttachmentParameter", + "attachment", + validAttachmentsForFBAttachment, + function(attachment) { + return gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + } + ); + if (contextVersion > 1) { + // test default framebuffer + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE'); + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.FRAMEBUFFER_DEFAULT'); + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.FRAMEBUFFER_DEFAULT'); + if (testCases[run].contextStencil) + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.FRAMEBUFFER_DEFAULT'); + else + shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_RED_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_GREEN_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_BLUE_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH, gl.FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)'); + if (testCases[run].contextStencil) { + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)'); + shouldBeNonZero('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)'); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + } else { + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE)'); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE)'); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.STENCIL, gl.FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING)'); + } + testInvalidArgument( + "getFramebufferAttachmentParameter", + "parameter", + validParametersForFBAttachment, + function(parameter) { + return gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.BACK, parameter); + } + ); + testInvalidArgument( + "getFramebufferAttachmentParameter", + "target", + validTargetsForFBAttachment, + function(target) { + return gl.getFramebufferAttachmentParameter(target, gl.BACK, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + } + ); + testInvalidArgument( + "getFramebufferAttachmentParameter", + "attachment", + [ gl.BACK, + gl.DEPTH, + gl.STENCIL + ], + function(attachment) { + return gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, attachment, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE); + } + ); + } +} +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug(""); +debug("test getAttachedShaders"); +var standardVert = wtu.loadStandardVertexShader(gl); +var standardFrag = wtu.loadStandardFragmentShader(gl); +var standardProgram = gl.createProgram(); +gl.attachShader(standardProgram, standardVert); +gl.attachShader(standardProgram, standardFrag); +gl.linkProgram(standardProgram); +var shaders = gl.getAttachedShaders(standardProgram); +shouldBe('shaders.length', '2'); +shouldBeTrue('shaders[0] == standardVert && shaders[1] == standardFrag || shaders[1] == standardVert && shaders[0] == standardFrag'); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); +shouldThrow('gl.getAttachedShaders(null)'); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); +shouldThrow('gl.getAttachedShaders(standardVert)'); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug(""); +debug("Test getProgramParameter"); +shouldBe('gl.getProgramParameter(standardProgram, gl.DELETE_STATUS)', 'false'); +shouldBe('gl.getProgramParameter(standardProgram, gl.LINK_STATUS)', 'true'); +shouldBe('typeof gl.getProgramParameter(standardProgram, gl.VALIDATE_STATUS)', '"boolean"'); +shouldBe('gl.getProgramParameter(standardProgram, gl.ATTACHED_SHADERS)', '2'); +shouldBe('gl.getProgramParameter(standardProgram, gl.ACTIVE_ATTRIBUTES)', '2'); +shouldBe('gl.getProgramParameter(standardProgram, gl.ACTIVE_UNIFORMS)', '1'); +if (contextVersion > 1) { + var buffer = gl.createBuffer(); + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buffer); + gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 1024, gl.DYNAMIC_DRAW); + var uniformBlockProgram = wtu.loadUniformBlockProgram(gl); + var transformFeedbackVars = ["normal", "ecPosition"]; + gl.transformFeedbackVaryings(uniformBlockProgram, transformFeedbackVars, gl.INTERLEAVED_ATTRIBS); + gl.linkProgram(uniformBlockProgram); + shouldBe('gl.getProgramParameter(uniformBlockProgram, gl.LINK_STATUS)', 'true'); + shouldBe('gl.getError()', 'gl.NO_ERROR'); + shouldBe('gl.getProgramParameter(uniformBlockProgram, gl.ACTIVE_UNIFORM_BLOCKS)', '1'); + shouldBe('gl.getProgramParameter(uniformBlockProgram, gl.TRANSFORM_FEEDBACK_VARYINGS)', '2'); + shouldBe('gl.getProgramParameter(uniformBlockProgram, gl.TRANSFORM_FEEDBACK_BUFFER_MODE)', 'gl.INTERLEAVED_ATTRIBS'); +} +var program = standardProgram; +var validArrayForProgramParameter = [ + gl.DELETE_STATUS, + gl.LINK_STATUS, + gl.VALIDATE_STATUS, + gl.ATTACHED_SHADERS, + gl.ACTIVE_ATTRIBUTES, + gl.ACTIVE_UNIFORMS +]; +if (contextVersion > 1) { + validArrayForProgramParameter = validArrayForProgramParameter.concat([ + gl.ACTIVE_UNIFORM_BLOCKS, + gl.TRANSFORM_FEEDBACK_VARYINGS, + gl.TRANSFORM_FEEDBACK_BUFFER_MODE + ]); + program = uniformBlockProgram; +} +testInvalidArgument( + "getProgramParameter", + "parameter", + validArrayForProgramParameter, + function(parameter) { + return gl.getProgramParameter(program, parameter); + } +); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug(""); +debug("Test getRenderbufferParameter"); +shouldBe('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)', '2'); +shouldBe('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)', '2'); +// Note: we can't test the actual value of the internal format since +// the implementation is allowed to change it. +shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_INTERNAL_FORMAT)'); +shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_DEPTH_SIZE)'); +var colorbuffer = gl.createRenderbuffer(); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); +gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); +gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 2, 2); +shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_RED_SIZE)'); +shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_GREEN_SIZE)'); +shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_BLUE_SIZE)'); +shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_ALPHA_SIZE)'); +if (contextVersion > 1) { + gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA4, 2, 2); + shouldBe('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_SAMPLES)', '4'); +} +var validArrayForRenderbuffer = new Array( + gl.RENDERBUFFER_WIDTH, + gl.RENDERBUFFER_HEIGHT, + gl.RENDERBUFFER_INTERNAL_FORMAT, + gl.RENDERBUFFER_RED_SIZE, + gl.RENDERBUFFER_GREEN_SIZE, + gl.RENDERBUFFER_BLUE_SIZE, + gl.RENDERBUFFER_ALPHA_SIZE, + gl.RENDERBUFFER_DEPTH_SIZE, + gl.RENDERBUFFER_STENCIL_SIZE +); +if (contextVersion > 1) { + validArrayForRenderbuffer[validArrayForRenderbuffer.length] = gl.RENDERBUFFER_SAMPLES; +} +testInvalidArgument( + "getRenderbufferParameter", + "parameter", + validArrayForRenderbuffer, + function(parameter) { + return gl.getRenderbufferParameter(gl.RENDERBUFFER, parameter); + }); +testInvalidArgument( + "getRenderbufferParameter", + "target", + [ gl.RENDERBUFFER ], + function(target) { + return gl.getRenderbufferParameter(target, gl.RENDERBUFFER_WIDTH); + } +); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug(""); +debug("Test getShaderParameter"); +shouldBe('gl.getShaderParameter(standardVert, gl.SHADER_TYPE)', 'gl.VERTEX_SHADER'); +shouldBe('gl.getShaderParameter(standardVert, gl.DELETE_STATUS)', 'false'); +shouldBe('gl.getShaderParameter(standardVert, gl.COMPILE_STATUS)', 'true'); +testInvalidArgument( + "getShaderParameter", + "parameter", + [ gl.DELETE_STATUS, + gl.COMPILE_STATUS, + gl.SHADER_TYPE + ], + function(parameter) { + return gl.getShaderParameter(standardVert, parameter); + } +); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug(""); +debug("Test getTexParameter"); +gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); +gl.bindTexture(gl.TEXTURE_2D, texture); +gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); +gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); +gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); +gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); +shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER)', 'gl.NEAREST'); +shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER)', 'gl.NEAREST'); +shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)', 'gl.CLAMP_TO_EDGE'); +shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T)', 'gl.CLAMP_TO_EDGE'); +if (contextVersion > 1) { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL, 0); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL, 10); + gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAX_LOD, 10); + gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_LOD, 0); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL)', '0'); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_FUNC)', 'gl.LEQUAL'); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_COMPARE_MODE)', 'gl.COMPARE_REF_TO_TEXTURE'); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL)', '10'); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MAX_LOD)', '10'); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MIN_LOD)', '0'); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R)', 'gl.CLAMP_TO_EDGE'); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_IMMUTABLE_FORMAT)', 'false'); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_IMMUTABLE_LEVELS)', '0'); +} +var validParametersForTexture = [ + gl.TEXTURE_MAG_FILTER, + gl.TEXTURE_MIN_FILTER, + gl.TEXTURE_WRAP_S, + gl.TEXTURE_WRAP_T, +]; +if (contextVersion > 1) { + validParametersForTexture = validParametersForTexture.concat([ + gl.TEXTURE_BASE_LEVEL, + gl.TEXTURE_COMPARE_FUNC, + gl.TEXTURE_COMPARE_MODE, + gl.TEXTURE_MAX_LEVEL, + gl.TEXTURE_MAX_LOD, + gl.TEXTURE_MIN_LOD, + gl.TEXTURE_WRAP_R, + gl.TEXTURE_IMMUTABLE_FORMAT, + gl.TEXTURE_IMMUTABLE_LEVELS, + ]); +} +testInvalidArgument( + "getTexParameter", + "parameter", + validParametersForTexture, + function(parameter) { + return gl.getTexParameter(gl.TEXTURE_2D, parameter); + } +); +var validTargetsForTexture = [ gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP]; +if (contextVersion > 1) { + validTargetsForTexture = validTargetsForTexture.concat([ gl.TEXTURE_3D, gl.TEXTURE_2D_ARRAY]); +} +testInvalidArgument( + "getTexParameter", + "target", + validTargetsForTexture, + function(target) { + return gl.getTexParameter(target, gl.TEXTURE_MAG_FILTER); + } +); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug(""); +debug("Test getUniform with all variants of data types"); +debug("Boolean uniform variables"); +var boolProgram = wtu.loadProgramFromFile(gl, "../../resources/boolUniformShader.vert", "../../resources/noopUniformShader.frag"); +shouldBe('gl.getProgramParameter(boolProgram, gl.LINK_STATUS)', 'true'); +var bvalLoc = gl.getUniformLocation(boolProgram, "bval"); +var bval2Loc = gl.getUniformLocation(boolProgram, "bval2"); +var bval3Loc = gl.getUniformLocation(boolProgram, "bval3"); +var bval4Loc = gl.getUniformLocation(boolProgram, "bval4"); +gl.useProgram(boolProgram); +gl.uniform1i(bvalLoc, 1); +gl.uniform2i(bval2Loc, 1, 0); +gl.uniform3i(bval3Loc, 1, 0, 1); +gl.uniform4i(bval4Loc, 1, 0, 1, 0); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); +shouldBe('gl.getUniform(boolProgram, bvalLoc)', 'true'); +shouldBe('gl.getUniform(boolProgram, bval2Loc)', '[true, false]'); +shouldBe('gl.getUniform(boolProgram, bval3Loc)', '[true, false, true]'); +shouldBe('gl.getUniform(boolProgram, bval4Loc)', '[true, false, true, false]'); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug("Integer uniform variables"); +var intProgram = wtu.loadProgramFromFile(gl, "../../resources/intUniformShader.vert", "../../resources/noopUniformShader.frag"); +shouldBe('gl.getProgramParameter(intProgram, gl.LINK_STATUS)', 'true'); +var ivalLoc = gl.getUniformLocation(intProgram, "ival"); +var ival2Loc = gl.getUniformLocation(intProgram, "ival2"); +var ival3Loc = gl.getUniformLocation(intProgram, "ival3"); +var ival4Loc = gl.getUniformLocation(intProgram, "ival4"); +gl.useProgram(intProgram); +gl.uniform1i(ivalLoc, 1); +gl.uniform2i(ival2Loc, 2, 3); +gl.uniform3i(ival3Loc, 4, 5, 6); +gl.uniform4i(ival4Loc, 7, 8, 9, 10); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); +shouldBe('gl.getUniform(intProgram, ivalLoc)', '1'); +shouldBe('gl.getUniform(intProgram, ival2Loc)', '[2, 3]'); +shouldBe('gl.getUniform(intProgram, ival3Loc)', '[4, 5, 6]'); +shouldBe('gl.getUniform(intProgram, ival4Loc)', '[7, 8, 9, 10]'); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug("Float uniform variables"); +var floatProgram = wtu.loadProgramFromFile(gl, "../../resources/floatUniformShader.vert", "../../resources/noopUniformShader.frag"); +shouldBe('gl.getProgramParameter(floatProgram, gl.LINK_STATUS)', 'true'); +var fvalLoc = gl.getUniformLocation(floatProgram, "fval"); +var fval2Loc = gl.getUniformLocation(floatProgram, "fval2"); +var fval3Loc = gl.getUniformLocation(floatProgram, "fval3"); +var fval4Loc = gl.getUniformLocation(floatProgram, "fval4"); +gl.useProgram(floatProgram); +gl.uniform1f(fvalLoc, 11); +gl.uniform2f(fval2Loc, 12, 13); +gl.uniform3f(fval3Loc, 14, 15, 16); +gl.uniform4f(fval4Loc, 17, 18, 19, 20); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); +shouldBe('gl.getUniform(floatProgram, fvalLoc)', '11'); +shouldBe('gl.getUniform(floatProgram, fval2Loc)', '[12, 13]'); +shouldBe('gl.getUniform(floatProgram, fval3Loc)', '[14, 15, 16]'); +shouldBe('gl.getUniform(floatProgram, fval4Loc)', '[17, 18, 19, 20]'); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug("Sampler uniform variables"); +var samplerProgram = wtu.loadProgramFromFile(gl, "../../resources/noopUniformShader.vert", "../../resources/samplerUniformShader.frag"); +shouldBe('gl.getProgramParameter(samplerProgram, gl.LINK_STATUS)', 'true'); +var s2DValLoc = gl.getUniformLocation(samplerProgram, "s2D"); +var sCubeValLoc = gl.getUniformLocation(samplerProgram, "sCube"); +gl.useProgram(samplerProgram); +gl.uniform1i(s2DValLoc, 0); +gl.uniform1i(sCubeValLoc, 1); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); +shouldBe('gl.getUniform(samplerProgram, s2DValLoc)', '0'); +shouldBe('gl.getUniform(samplerProgram, sCubeValLoc)', '1'); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug("Matrix uniform variables"); +var matProgram = wtu.loadProgramFromFile(gl, "../../resources/matUniformShader.vert", "../../resources/noopUniformShader.frag"); +shouldBe('gl.getProgramParameter(matProgram, gl.LINK_STATUS)', 'true'); +var mval2Loc = gl.getUniformLocation(matProgram, "mval2"); +var mval3Loc = gl.getUniformLocation(matProgram, "mval3"); +var mval4Loc = gl.getUniformLocation(matProgram, "mval4"); +gl.useProgram(matProgram); +gl.uniformMatrix2fv(mval2Loc, false, [1, 2, 3, 4]); +gl.uniformMatrix3fv(mval3Loc, false, [5, 6, 7, 8, 9, 10, 11, 12, 13]); +gl.uniformMatrix4fv(mval4Loc, false, [14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); +shouldBe('gl.getUniform(matProgram, mval2Loc)', '[1, 2, 3, 4]'); +shouldBe('gl.getUniform(matProgram, mval3Loc)', '[5, 6, 7, 8, 9, 10, 11, 12, 13]'); +shouldBe('gl.getUniform(matProgram, mval4Loc)', '[14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]'); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +if (contextVersion > 1) { + debug("Unsigned Integer uniform variables"); + var uintProgram = wtu.loadProgramFromFile(gl, "../../resources/uintUniformShader.vert", "../../resources/noopUniformShaderES3.frag"); + shouldBe('gl.getProgramParameter(uintProgram, gl.LINK_STATUS)', 'true'); + var uvalLoc = gl.getUniformLocation(uintProgram, "uval"); + var uval2Loc = gl.getUniformLocation(uintProgram, "uval2"); + var uval3Loc = gl.getUniformLocation(uintProgram, "uval3"); + var uval4Loc = gl.getUniformLocation(uintProgram, "uval4"); + gl.useProgram(uintProgram); + gl.uniform1ui(uvalLoc, 1); + gl.uniform2ui(uval2Loc, 2, 3); + gl.uniform3ui(uval3Loc, 4, 5, 6); + gl.uniform4ui(uval4Loc, 7, 8, 9, 10); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + shouldBe('gl.getUniform(uintProgram, uvalLoc)', '1'); + shouldBe('gl.getUniform(uintProgram, uval2Loc)', '[2, 3]'); + shouldBe('gl.getUniform(uintProgram, uval3Loc)', '[4, 5, 6]'); + shouldBe('gl.getUniform(uintProgram, uval4Loc)', '[7, 8, 9, 10]'); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + debug("Matrix uniform variables for WebGL 2"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + var matForWebGL2Program = wtu.loadProgramFromFile(gl, "../../resources/matForWebGL2UniformShader.vert", "../../resources/noopUniformShaderES3.frag"); + shouldBe('gl.getProgramParameter(matForWebGL2Program, gl.LINK_STATUS)', 'true'); + var mval2x3Loc = gl.getUniformLocation(matForWebGL2Program, "mval2x3"); + var mval2x4Loc = gl.getUniformLocation(matForWebGL2Program, "mval2x4"); + var mval3x2Loc = gl.getUniformLocation(matForWebGL2Program, "mval3x2"); + var mval3x4Loc = gl.getUniformLocation(matForWebGL2Program, "mval3x4"); + var mval4x2Loc = gl.getUniformLocation(matForWebGL2Program, "mval4x2"); + var mval4x3Loc = gl.getUniformLocation(matForWebGL2Program, "mval4x3"); + gl.useProgram(matForWebGL2Program); + gl.uniformMatrix2x3fv(mval2x3Loc, false, [1, 2, 3, 4, 5, 6]); + gl.uniformMatrix2x4fv(mval2x4Loc, false, [7, 8, 9, 10, 11, 12, 13, 14]); + gl.uniformMatrix3x2fv(mval3x2Loc, false, [15, 16, 17, 18, 19, 20]); + gl.uniformMatrix3x4fv(mval3x4Loc, false, [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]); + gl.uniformMatrix4x2fv(mval4x2Loc, false, [33, 34, 35, 36, 37, 38, 39, 40]); + gl.uniformMatrix4x3fv(mval4x3Loc, false, [41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + shouldBe('gl.getUniform(matForWebGL2Program, mval2x3Loc)', '[1, 2, 3, 4, 5, 6]'); + shouldBe('gl.getUniform(matForWebGL2Program, mval2x4Loc)', '[7, 8, 9, 10, 11, 12, 13, 14]'); + shouldBe('gl.getUniform(matForWebGL2Program, mval3x2Loc)', '[15, 16, 17, 18, 19, 20]'); + shouldBe('gl.getUniform(matForWebGL2Program, mval3x4Loc)', '[21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]'); + shouldBe('gl.getUniform(matForWebGL2Program, mval4x2Loc)', '[33, 34, 35, 36, 37, 38, 39, 40]'); + shouldBe('gl.getUniform(matForWebGL2Program, mval4x3Loc)', '[41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52]'); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + debug("Sampler uniform variables for WebGL2"); + var samplerForWebGL2Program = wtu.loadProgramFromFile(gl, "../../resources/noopUniformShaderES3.vert", "../../resources/samplerForWebGL2UniformShader.frag"); + shouldBe('gl.getProgramParameter(samplerForWebGL2Program, gl.LINK_STATUS)', 'true'); + var s3DValLoc = gl.getUniformLocation(samplerForWebGL2Program, "s3D"); + var s2DArrayValLoc = gl.getUniformLocation(samplerForWebGL2Program, "s2DArray"); + gl.useProgram(samplerForWebGL2Program); + gl.uniform1i(s3DValLoc, 0); + gl.uniform1i(s2DArrayValLoc, 1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + shouldBe('gl.getUniform(samplerForWebGL2Program, s3DValLoc)', '0'); + shouldBe('gl.getUniform(samplerForWebGL2Program, s2DArrayValLoc)', '1'); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); +} + +debug(""); +debug("test getVertexAttrib"); +var array = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); +var buffer = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, buffer); +gl.bufferData(gl.ARRAY_BUFFER, array, gl.DYNAMIC_DRAW); +// Vertex attribute 0 is special in that it has no current state, so +// fetching GL_CURRENT_VERTEX_ATTRIB generates an error. Use attribute +// 1 for these tests instead. +gl.enableVertexAttribArray(1); +gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 0, 0); +shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)', 'buffer'); +shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_ENABLED)', 'true'); +shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_SIZE)', '4'); +// Stride MUST be the value the user put in. +shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_STRIDE)', '0'); +shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_TYPE)', 'gl.FLOAT'); +shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED)', 'false'); +if (contextVersion > 1) { + shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_DIVISOR)', '0'); + shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_INTEGER)', 'false'); + gl.vertexAttribDivisor(1, 2); + shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_DIVISOR)', '2'); +} +gl.vertexAttribPointer(1, 4, gl.FLOAT, false, 36, 12); +shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_STRIDE)', '36'); +shouldBe('gl.getVertexAttribOffset(1, gl.VERTEX_ATTRIB_ARRAY_POINTER)', '12'); +gl.disableVertexAttribArray(1); +shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_ENABLED)', 'false'); +gl.vertexAttrib4f(1, 5, 6, 7, 8); +shouldBe('gl.getVertexAttrib(1, gl.CURRENT_VERTEX_ATTRIB)', '[5, 6, 7, 8]'); +if (contextVersion > 1) { + var intArray = new Int32Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); + gl.bufferData(gl.ARRAY_BUFFER, intArray, gl.DYNAMIC_DRAW); + gl.enableVertexAttribArray(1); + // feed fixed-point data to buffer + gl.vertexAttribIPointer(1, 4, gl.INT, false, 0, 0); + shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_TYPE)', 'gl.INT'); + shouldBe('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_INTEGER)', 'true'); +} +wtu.glErrorShouldBe(gl, gl.NO_ERROR); +var validArrayForVertexAttrib = new Array( + gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, + gl.VERTEX_ATTRIB_ARRAY_ENABLED, + gl.VERTEX_ATTRIB_ARRAY_SIZE, + gl.VERTEX_ATTRIB_ARRAY_STRIDE, + gl.VERTEX_ATTRIB_ARRAY_TYPE, + gl.VERTEX_ATTRIB_ARRAY_NORMALIZED, + gl.CURRENT_VERTEX_ATTRIB +); +if (contextVersion > 1) { + validArrayForVertexAttrib[validArrayForVertexAttrib.length] = gl.VERTEX_ATTRIB_ARRAY_DIVISOR; + validArrayForVertexAttrib[validArrayForVertexAttrib.length] = gl.VERTEX_ATTRIB_ARRAY_INTEGER; +} +testInvalidArgument( + "getVertexAttrib", + "parameter", + validArrayForVertexAttrib, + function(parameter) { + return gl.getVertexAttrib(1, parameter); + } +); +var numVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); +wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, 'gl.getVertexAttrib(' + numVertexAttribs + ', gl.CURRENT_VERTEX_ATTRIB)'); + +debug(""); +debug("Test cases where name == 0"); +gl.deleteTexture(texture); +shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE'); +gl.deleteRenderbuffer(renderbuffer); +gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer); +wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION); +shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.NONE'); +gl.deleteBuffer(buffer); +shouldBeNull('gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)'); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +if (contextVersion > 1) { + debug(""); + debug("Test getInternalformatParameter") + + shouldBeNonNull('gl.getInternalformatParameter(gl.RENDERBUFFER, gl.R32I, gl.SAMPLES)'); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + testInvalidArgument( + "getInternalformatParameter", + "target", + [ gl.RENDERBUFFER ], + function(target) { + return gl.getInternalformatParameter(target, gl.R32I, gl.SAMPLES); + }); + + testInvalidArgument( + "getInternalformatParameter", + "pname", + [ gl.SAMPLES ], + function(pname) { + return gl.getInternalformatParameter(gl.RENDERBUFFER, gl.RGBA4, pname); + }); + + var validArrayForInterformat = new Array( + gl.R8, gl.R8_SNORM, gl.RG8, gl.RG8_SNORM, + gl.RGB8, gl.RGB8_SNORM, gl.RGB565, gl.RGBA4, + gl.RGB5_A1, gl.RGBA8, gl.RGBA8_SNORM, gl.RGB10_A2, + gl.RGB10_A2UI, gl.SRGB8, gl.SRGB8_ALPHA8, gl.R16F, + gl.RG16F, gl.RGB16F, gl.RGBA16F, gl.R32F, + gl.RG32F, gl.RGB32F, gl.RGBA32F, gl.R11F_G11F_B10F, + gl.RGB9_E5, gl.R8I, gl.R8UI, gl.R16I, + gl.R16UI, gl.R32I, gl.R32UI, gl.RG8I, + gl.RG8UI, gl.RG16I, gl.RG16UI, gl.RG32I, + gl.RG32UI, gl.RGB8I, gl.RGB8UI, gl.RGB16I, + gl.RGB16UI, gl.RGB32I, gl.RGB32UI, gl.RGBA8I, + gl.RGBA8UI, gl.RGBA16I, gl.RGBA16UI, gl.RGBA32I, + gl.RGBA32UI, gl.RGB, gl.RGBA, gl.DEPTH_STENCIL, gl.DEPTH_COMPONENT16, + gl.DEPTH_COMPONENT24, gl.DEPTH_COMPONENT32F, gl.DEPTH24_STENCIL8, + gl.DEPTH32F_STENCIL8, gl.STENCIL_INDEX8 + ); + testInvalidArgument( + "getInternalformatParameter", + "internalformat", + validArrayForInterformat, + function(internalformat) { + return gl.getInternalformatParameter(gl.RENDERBUFFER, internalformat, gl.SAMPLES); + }); + + + debug(""); + debug("Test getIndexedParameter"); + var buffer = gl.createBuffer(); + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buffer); + gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 64, gl.DYNAMIC_DRAW); + gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer, 4, 8); + shouldBe('gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)', 'buffer'); + shouldBe('gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)', '8'); + shouldBe('gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)', '4'); + var buffer1 = gl.createBuffer(); + gl.bindBuffer(gl.UNIFORM_BUFFER, buffer1); + gl.bufferData(gl.UNIFORM_BUFFER, 64, gl.DYNAMIC_DRAW); + var offsetUniform = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT); + gl.bindBufferRange(gl.UNIFORM_BUFFER, 1, buffer1, offsetUniform, 8); + shouldBe('gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)', 'buffer1'); + shouldBe('gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)', '8'); + shouldBe('gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)', 'offsetUniform'); + + gl.bindBufferBase(gl.UNIFORM_BUFFER, 1, null); + shouldBe('gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)', 'null'); + + var validArrayForTarget = new Array( + gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, + gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, + gl.TRANSFORM_FEEDBACK_BUFFER_START, + gl.UNIFORM_BUFFER_BINDING, + gl.UNIFORM_BUFFER_SIZE, + gl.UNIFORM_BUFFER_START + ); + testInvalidArgument( + "getIndexedParameter", + "target", + validArrayForTarget, + function(target) { + return gl.getIndexedParameter(target, 0); + }); + + debug(""); + debug("Test getSamplerParameter"); + var sampler = gl.createSampler(); + gl.samplerParameteri(sampler, gl.TEXTURE_COMPARE_FUNC, gl.LEQUAL); + gl.samplerParameteri(sampler, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE); + gl.samplerParameteri(sampler, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.samplerParameterf(sampler, gl.TEXTURE_MAX_LOD, 10); + gl.samplerParameteri(sampler, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.samplerParameterf(sampler, gl.TEXTURE_MIN_LOD, 0); + gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); + gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.samplerParameteri(sampler, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_COMPARE_FUNC)', 'gl.LEQUAL'); + shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_COMPARE_MODE)', 'gl.COMPARE_REF_TO_TEXTURE'); + shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_MAG_FILTER)', 'gl.NEAREST'); + shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_MAX_LOD)', '10'); + shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_MIN_FILTER)', 'gl.NEAREST'); + shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_MIN_LOD)', '0'); + shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_WRAP_R)', 'gl.CLAMP_TO_EDGE'); + shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_WRAP_S)', 'gl.CLAMP_TO_EDGE'); + shouldBe('gl.getSamplerParameter(sampler, gl.TEXTURE_WRAP_T)', 'gl.CLAMP_TO_EDGE'); + var validArrayForSamplerParameter = new Array( + gl.TEXTURE_COMPARE_FUNC, + gl.TEXTURE_COMPARE_MODE, + gl.TEXTURE_MAG_FILTER, + gl.TEXTURE_MAX_LOD, + gl.TEXTURE_MIN_FILTER, + gl.TEXTURE_MIN_LOD, + gl.TEXTURE_WRAP_R, + gl.TEXTURE_WRAP_S, + gl.TEXTURE_WRAP_T + ); + testInvalidArgument( + "getSamplerParameter", + "pname", + validArrayForSamplerParameter, + function(pname) { + return gl.getSamplerParameter(sampler, pname); + }); + + debug(""); + debug("Test getSyncParameter"); + var sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0); + shouldBe('gl.getSyncParameter(sync, gl.OBJECT_TYPE)', 'gl.SYNC_FENCE'); + var sync_status = gl.getSyncParameter(sync, gl.SYNC_STATUS); + switch (sync_status) { + case gl.UNSIGNALED: + testPassed('gl.getSyncParameter(sync, gl.SYNC_CONDITION) is gl.UNSIGNALED'); + break; + case gl.SIGNALED: + testPassed('gl.getSyncParameter(sync, gl.SYNC_CONDITION) is gl.SIGNALED'); + break; + default: + testFailed('gl.getSyncParameter(sync, gl.SYNC_CONDITION) was ' + sync_status + + ', expected gl.UNSIGNALED or gl.SIGNALED'); + break; + } + shouldBe('gl.getSyncParameter(sync, gl.SYNC_CONDITION)', 'gl.SYNC_GPU_COMMANDS_COMPLETE'); + shouldBe('gl.getSyncParameter(sync, gl.SYNC_FLAGS)', '0'); + var validArrayForSyncParameter = new Array( + gl.OBJECT_TYPE, + gl.SYNC_STATUS, + gl.SYNC_CONDITION, + gl.SYNC_FLAGS + ); + testInvalidArgument( + "getSyncParameter", + "pname", + validArrayForSyncParameter, + function(pname) { + return gl.getSyncParameter(sync, pname); + }); + + debug(""); + debug("Test getQueryParameter"); + var query = gl.createQuery(); + gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query); + gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); + shouldBe('gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE)', 'false'); + // Queries' results are tested elsewhere in the conformance suite. It's complicated + // to wait for this query's result to become available and verify it. + var validArrayForPname = new Array( + gl.QUERY_RESULT, + gl.QUERY_RESULT_AVAILABLE + ); + testInvalidArgument( + "getQueryParameter", + "pname", + validArrayForPname, + function(pname) { + return gl.getQueryParameter(query, pname); + } + ); + + debug(""); + debug("Test getFragDataLocation"); + var baseVertShader = '' + + '#version 300 es\n' + + 'uniform mat4 modelViewMatrix;\n' + + 'uniform mat4 projectionMatrix;\n' + + 'in vec4 vertex;\n' + + 'out vec4 position;\n' + + 'void main (void)\n' + + '{\n' + + ' position = modelViewMatrix * vertex;\n' + + ' gl_Position = projectionMatrix * position;\n' + + '}\n'; + var baseFragShader = '' + + '#version 300 es\n' + + 'in lowp vec4 position;\n' + + 'layout(location = 0) out mediump vec4 fragColor;\n' + + 'void main (void)\n' + + '{\n' + + ' fragColor = position;\n' + + '}\n'; + var vertShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(vertShader, baseVertShader); + gl.compileShader(vertShader); + shouldBe('gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)', 'true'); + var fragShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(fragShader, baseFragShader); + gl.compileShader(fragShader); + shouldBe('gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)', 'true'); + var program = gl.createProgram(); + gl.attachShader(program, vertShader); + gl.attachShader(program, fragShader); + gl.linkProgram(program); + shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)','true'); + shouldBe('gl.getFragDataLocation(program, "vertexColor")', '-1'); + shouldBe('gl.getFragDataLocation(program, "modelViewMatrix")', '-1'); + shouldBe('gl.getFragDataLocation(program, "projectionMatrix")', '-1'); + shouldBe('gl.getFragDataLocation(program, "position")', '-1'); + shouldBe('gl.getFragDataLocation(program, "fragColor")', '0'); + + debug(""); + debug("Test getActiveUniforms"); + var program = wtu.loadUniformBlockProgram(gl); + gl.linkProgram(program); + shouldBe('gl.getProgramParameter(program, gl.LINK_STATUS)', 'true'); + shouldBe('gl.getError()', 'gl.NO_ERROR'); + + var numActiveUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); + var blockIndex = gl.getUniformBlockIndex(program, "Transform"); + var uniformIndices = []; + for (var i = 0; i < numActiveUniforms; i++) + uniformIndices.push(i); + var types = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_TYPE); + var sizes = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_SIZE); + var blockIndices = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_BLOCK_INDEX); + var offsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET); + var arrayStrides = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_ARRAY_STRIDE); + var matrixStrides = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_MATRIX_STRIDE); + var rowMajors = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_IS_ROW_MAJOR); + for (var i = 0; i < numActiveUniforms; i++) { + if (types[i] != gl.FLOAT_MAT4 && types[i] != gl.FLOAT_MAT3) + testFailed("expected value: GL_FLOAT_MAT4 or GL_FLOAT_MAT3" + " actual value for UNIFORM_TYPE for uniform index[" + i + "]:" + wtu.glEnumToString(gl, types[i])); + if (sizes[i] != 1) + testFailed("expected value: 1" + " actual value for UNIFORM_SIZE for uniform index[" + i + "]:" + sizes[i]); + if (blockIndices[i] != blockIndex) + testFailed("expected value: 0" + " actual value for UNIFORM_BLOCK_INDEX for uniform index[" + i + "]:" + blockIndices[i]); + if (offsets[i] < 0) + testFailed("expected value >= 0" + " actual value for UNIFORM_OFFSET for uniform index[" + i + "]:" + offsets[i]); + if (arrayStrides[i] != 0) + testFailed("expected value: 0" + " actual value for UNIFORM_ARRAY_STRIDE for uniform index[" + i + "]:" + arrayStrides[i]); + if (matrixStrides[i] < 0) + testFailed("expected value >= 0" + " actual value for UNIFORM_MATRIX_STRIDE for uniform index[" + i + "]:" + matrixStrides[i]); + shouldBe('typeof rowMajors[i]', '"boolean"'); + if (rowMajors[i] != false) + testFailed("expected value: 0" + " actual value for UNIFORM_IS_ROW_MAJOR for uniform index[" + i + "]:" + rowMajors[i]); + } + + var validArrayForPname = new Array( + gl.UNIFORM_TYPE, + gl.UNIFORM_SIZE, + gl.UNIFORM_BLOCK_INDEX, + gl.UNIFORM_OFFSET, + gl.UNIFORM_ARRAY_STRIDE, + gl.UNIFORM_MATRIX_STRIDE, + gl.UNIFORM_IS_ROW_MAJOR + ); + testInvalidArgument( + "getActiveUniforms", + "pname", + validArrayForPname, + function(pname) { + return gl.getActiveUniforms(program, uniformIndices, pname); + } + ); + + debug(""); + debug("Test getUniformBlockIndex"); + var program = wtu.loadUniformBlockProgram(gl); + gl.linkProgram(program); + shouldBeTrue('gl.getProgramParameter(program, gl.LINK_STATUS)'); + shouldBe('gl.getUniformBlockIndex(program, "Transform")', '0'); + shouldBe('gl.getUniformBlockIndex(program, "u_modelViewMatrix")', 'gl.INVALID_INDEX'); + shouldBe('gl.getUniformBlockIndex(program, "normal")', 'gl.INVALID_INDEX'); + shouldBe('gl.getUniformBlockIndex(program, "u_normal")', 'gl.INVALID_INDEX'); + var noUniformProgram = wtu.loadStandardProgram(gl); + gl.linkProgram(noUniformProgram); + shouldBeTrue('gl.getProgramParameter(noUniformProgram, gl.LINK_STATUS)'); + shouldBe('gl.getUniformBlockIndex(noUniformProgram, "u_modelViewProjMatrix")', 'gl.INVALID_INDEX'); + shouldBe('gl.getUniformBlockIndex(noUniformProgram, "u_normal")', 'gl.INVALID_INDEX'); + + debug(""); + debug("Test getActiveUniformBlockName"); + var program = wtu.loadUniformBlockProgram(gl); + gl.linkProgram(program); + shouldBeTrue('gl.getProgramParameter(program, gl.LINK_STATUS)'); + shouldBeEqualToString('gl.getActiveUniformBlockName(program, 0)', 'Transform'); + shouldBeNull('gl.getActiveUniformBlockName(program, -1)'); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + shouldBeNull('gl.getActiveUniformBlockName(program, 1)'); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + shouldBeNull('gl.getActiveUniformBlockName(program, gl.INVALID_INDEX)'); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + var noLinkProgram = gl.createProgram(); + shouldBeFalse('gl.getProgramParameter(noLinkProgram, gl.LINK_STATUS)'); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.getActiveUniformBlockName(noLinkProgram, 0)'); + var noUniformProgram = wtu.loadStandardProgram(gl); + gl.linkProgram(noUniformProgram); + shouldBeTrue('gl.getProgramParameter(noUniformProgram, gl.LINK_STATUS)'); + shouldBeNull('gl.getActiveUniformBlockName(noUniformProgram, -1)'); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + shouldBeNull('gl.getActiveUniformBlockName(noUniformProgram, 0)'); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + shouldBeNull('gl.getActiveUniformBlockName(noUniformProgram, gl.INVALID_INDEX)'); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + debug(""); + debug("Test getActiveUniformBlockParameter"); + var program = wtu.loadUniformBlockProgram(gl); + gl.linkProgram(program); + shouldBeTrue('gl.getProgramParameter(program, gl.LINK_STATUS)'); + shouldBe('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_BINDING)', '0'); + gl.uniformBlockBinding(program, 0, 1); + shouldBe('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_BINDING)', '1'); + // The actual block data size can be bigger than 164, depending on the uniform block layout. + shouldBeTrue('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_DATA_SIZE) >= 164'); + shouldBe('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_ACTIVE_UNIFORMS)', '3'); + shouldBeTrue('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER)'); + shouldBeFalse('gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER)'); + var indices = gl.getActiveUniformBlockParameter(program, 0, gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES); + for (var i = 0; i < 3; i++) { + if (indices[i] < 0) + testFailed("expected value >= 0" + " actual value for UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES for uniform index[" + i + "]:" + indices[i]); + } + var validArrayForPname = new Array( + gl.UNIFORM_BLOCK_BINDING, + gl.UNIFORM_BLOCK_DATA_SIZE, + gl.UNIFORM_BLOCK_ACTIVE_UNIFORMS, + gl.UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, + gl.UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, + gl.UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER + ); + testInvalidArgument( + "getActiveUniformBlockParameter", + "pname", + validArrayForPname, + function(pname) { + return gl.getActiveUniformBlockParameter(program, 0, pname); + } + ); +} + +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +var successfullyParsed = true; diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/gl-vertex-attrib.js b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-vertex-attrib.js new file mode 100644 index 000000000..ddff0e550 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/gl-vertex-attrib.js @@ -0,0 +1,280 @@ +/* +** Copyright (c) 2015 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. +*/ + +// This test relies on the surrounding web page defining a variable +// "contextVersion" which indicates what version of WebGL it's running +// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc. + +"use strict"; +description("This test ensures WebGL implementations vertexAttrib can be set and read."); + +debug(""); +debug("Canvas.getContext"); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext("canvas", undefined, contextVersion); +if (!gl) { + testFailed("context does not exist"); +} else { + testPassed("context exists"); + + debug(""); + debug("Checking gl.vertexAttrib."); + + var numVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + for (var ii = 0; ii < numVertexAttribs; ++ii) { + gl.vertexAttrib1fv(ii, [1]); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1'); + + gl.vertexAttrib1fv(ii, new Float32Array([-1])); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '-1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1'); + + gl.vertexAttrib2fv(ii, [1, 2]); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '2'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1'); + + gl.vertexAttrib2fv(ii, new Float32Array([1, -2])); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '-2'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1'); + + gl.vertexAttrib3fv(ii, [1, 2, 3]); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '2'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '3'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1'); + + gl.vertexAttrib3fv(ii, new Float32Array([1, -2, 3])); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '-2'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '3'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1'); + + gl.vertexAttrib4fv(ii, [1, 2, 3, 4]); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '2'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '3'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '4'); + + gl.vertexAttrib4fv(ii, new Float32Array([1, 2, -3, 4])); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '2'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '-3'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '4'); + + gl.vertexAttrib1f(ii, 5); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '5'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1'); + + gl.vertexAttrib2f(ii, 6, 7); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '6'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '7'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1'); + + gl.vertexAttrib3f(ii, 7, 8, 9); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '7'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '8'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '9'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '1'); + + gl.vertexAttrib4f(ii, 6, 7, 8, 9); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Float32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '6'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '7'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '8'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '9'); + + if (contextVersion > 1) { + gl.vertexAttribI4i(ii, -1, 0, 1, 2); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Int32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '-1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '2'); + + gl.vertexAttribI4ui(ii, 0, 1, 2, 3); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Uint32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '2'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '3'); + + gl.vertexAttribI4iv(ii, [-1, 0, 1, 2]); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Int32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '-1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '2'); + + gl.vertexAttribI4iv(ii, new Int32Array([1, 0, -1, 2])); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Int32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '-1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '2'); + + gl.vertexAttribI4uiv(ii, [0, 1, 2, 3]); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Uint32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '2'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '3'); + + gl.vertexAttribI4uiv(ii, new Uint32Array([0, 2, 1, 3])); + shouldBeType('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)', 'Uint32Array'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[0]', '0'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[1]', '2'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[2]', '1'); + shouldBe('gl.getVertexAttrib(' + ii + ', gl.CURRENT_VERTEX_ATTRIB)[3]', '3'); + } + } + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + debug(""); + debug("Checking out-of-range vertexAttrib index"); + gl.getVertexAttrib(numVertexAttribs, gl.CURRENT_VERTEX_ATTRIB); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib1fv(numVertexAttribs, [1]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib1fv(numVertexAttribs, new Float32Array([-1])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib2fv(numVertexAttribs, [1, 2]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib2fv(numVertexAttribs, new Float32Array([1, -2])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib3fv(numVertexAttribs, [1, 2, 3]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib3fv(numVertexAttribs, new Float32Array([1, -2, 3])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib4fv(numVertexAttribs, [1, 2, 3, 4]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib4fv(numVertexAttribs, new Float32Array([1, 2, -3, 4])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib1f(numVertexAttribs, 5); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib2f(numVertexAttribs, 6, 7); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib3f(numVertexAttribs, 7, 8, 9); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib4f(numVertexAttribs, 6, 7, 8, 9); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + if (contextVersion > 1) { + gl.vertexAttribI4i(numVertexAttribs, -1, 0, 1, 2); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttribI4ui(numVertexAttribs, 0, 1, 2, 3); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttribI4iv(numVertexAttribs, [-1, 0, 1, 2]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttribI4iv(numVertexAttribs, new Int32Array([1, 0, -1, 2])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttribI4uiv(numVertexAttribs, [0, 1, 2, 3]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttribI4uiv(numVertexAttribs, new Uint32Array([0, 2, 1, 3])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + } + + debug(""); + debug("Checking invalid array lengths"); + numVertexAttribs = numVertexAttribs - 1; + gl.vertexAttrib1fv(numVertexAttribs, []); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib1fv(numVertexAttribs, new Float32Array([])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib2fv(numVertexAttribs, [1]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib2fv(numVertexAttribs, new Float32Array([1])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib3fv(numVertexAttribs, [1, 2]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib3fv(numVertexAttribs, new Float32Array([1, -2])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib4fv(numVertexAttribs, [1, 2, 3]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttrib4fv(numVertexAttribs, new Float32Array([1, 2, -3])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + if (contextVersion > 1) { + gl.vertexAttribI4iv(numVertexAttribs, [-1, 0, 1]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttribI4iv(numVertexAttribs, new Int32Array([1, 0, -1])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttribI4uiv(numVertexAttribs, [0, 1, 2]); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + + gl.vertexAttribI4uiv(numVertexAttribs, new Uint32Array([0, 2, 1])); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); + } +} + +debug(""); +var successfullyParsed = true; diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/instanceof-test.js b/dom/canvas/test/webgl-conf/checkout/js/tests/instanceof-test.js new file mode 100644 index 000000000..bd1ca2af8 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/instanceof-test.js @@ -0,0 +1,122 @@ +/* +** Copyright (c) 2015 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. +*/ + +// This test relies on the surrounding web page defining a variable +// "contextVersion" which indicates what version of WebGL it's running +// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc. + +"use strict"; +var wtu = WebGLTestUtils; +description(document.title); +debug("Tests that instanceof works on WebGL objects."); +debug(""); + +function checkGLError(message) { + var error = gl.getError(); + if (error != gl.NO_ERROR) { + wtu.error("Error: " + message + " caused " + wtu.glEnumToString(gl, error)); + } +} + +var gl = wtu.create3DContext("canvas", undefined, contextVersion); +if (contextVersion === 1) { + shouldBeTrue('gl instanceof WebGLRenderingContext'); +} else if (contextVersion === 2) { + shouldBeTrue('gl instanceof WebGL2RenderingContext'); +} + +shouldBeTrue('gl.createBuffer() instanceof WebGLBuffer'); +checkGLError("createBuffer") + +shouldBeTrue('gl.createFramebuffer() instanceof WebGLFramebuffer'); +checkGLError("createFramebuffer") + +shouldBeTrue('gl.createProgram() instanceof WebGLProgram'); +checkGLError("createProgram") + +shouldBeTrue('gl.createRenderbuffer() instanceof WebGLRenderbuffer'); +checkGLError("createRenderbuffer") + +shouldBeTrue('gl.createShader(gl.VERTEX_SHADER) instanceof WebGLShader'); +checkGLError("createShader") + +shouldBeTrue('gl.createTexture() instanceof WebGLTexture'); +checkGLError("createTexture") + +if (contextVersion > 1) { + shouldBeTrue('gl.createQuery() instanceof WebGLQuery'); + checkGLError("createQuery") + + shouldBeTrue('gl.createSampler() instanceof WebGLSampler'); + checkGLError("createSampler") + + shouldBeTrue('gl.createTransformFeedback() instanceof WebGLTransformFeedback'); + checkGLError("createTransformFeedback") + + shouldBeTrue('gl.createVertexArray() instanceof WebGLVertexArrayObject'); + checkGLError("createVertexArray") +} + +var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['vPosition'], [0]); + +shouldBeTrue('gl.getUniformLocation(program, "color") instanceof WebGLUniformLocation'); +checkGLError("getUniformLocation") + +shouldBeTrue('gl.getActiveAttrib(program, 0) instanceof WebGLActiveInfo'); +checkGLError("getActiveAttrib") + +shouldBeTrue('gl.getActiveUniform(program, 0) instanceof WebGLActiveInfo'); +checkGLError("getActiveUniform") + +debug(""); +debug("Tests that those WebGL objects can not be constructed through new operator"); +debug(""); + +function shouldThrowWithNew(objectType, objectName) { + try { + new objectType; + testFailed('new ' + objectName + ' did not throw'); + } catch (e) { + testPassed('new ' + objectName + ' threw an error'); + } +} + +shouldThrowWithNew(window.WebGLRenderingContext, 'WebGLRenderingContext'); +shouldThrowWithNew(window.WebGLActiveInfo, 'WebGLActiveInfo'); +shouldThrowWithNew(window.WebGLBuffer, 'WebGLBuffer'); +shouldThrowWithNew(window.WebGLFramebuffer, 'WebGLFramebuffer'); +shouldThrowWithNew(window.WebGLProgram, 'WebGLProgram'); +shouldThrowWithNew(window.WebGLRenderbuffer, 'WebGLRenderbuffer'); +shouldThrowWithNew(window.WebGLShader, 'WebGLShader'); +shouldThrowWithNew(window.WebGLTexture, 'WebGLTexture'); +shouldThrowWithNew(window.WebGLUniformLocation, 'WebGLUniformLocation'); +shouldThrowWithNew(window.WebGLShaderPrecisionFormat, 'WebGLShaderPrecisionFormat'); +if (contextVersion > 1) { + shouldThrowWithNew(window.WebGLQuery, 'WebGLQuery'); + shouldThrowWithNew(window.WebGLSampler, 'WebGLSampler'); + shouldThrowWithNew(window.WebGLSync, 'WebGLSync'); + shouldThrowWithNew(window.WebGLTransformFeedback, 'WebGLTransformFeedback'); + shouldThrowWithNew(window.WebGLVertexArrayObject, 'WebGLVertexArrayObject'); +} + +var successfullyParsed = true; diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/iterable-test.js b/dom/canvas/test/webgl-conf/checkout/js/tests/iterable-test.js new file mode 100644 index 000000000..31abe5011 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/iterable-test.js @@ -0,0 +1,173 @@ +/* +** Copyright (c) 2013 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. +*/ +IterableTest = (function() { + + var wtu = WebGLTestUtils; + + function run(test, iterations) { + var target = iterations || 10; + var count = 0; + + function doNextTest() { + ++count; + debug("Test " + count + " of " + target); + var success = test(); + if (count < target && success !== false) { + wtu.waitForComposite(doNextTest); + //setTimeout(doNextTest, 100); + } else { + finishTest(); + } + } + + doNextTest(); + } + + // Creates a canvas and a texture then exits. There are + // no references to either so both should be garbage collected. + function createContextCreationAndDestructionTest() { + var textureSize = null; + + return function() { + var canvas = document.createElement("canvas"); + // This is safe for any device. See drawingBufferWidth in spec. + canvas.width = 2048; + canvas.height = 2048; + var gl = wtu.create3DContext(canvas); + if (textureSize === null) { + var maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); + textureSize = Math.min(1024, maxTextureSize); + } + var tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, textureSize, textureSize, 0, gl.RGBA, gl.UNSIGNED_BYTE, + null); + gl.clear(gl.COLOR_BUFFER_BIT); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors"); + + return true; + }; + } + + // Creates many small canvases and attaches them to the DOM. + // This tests an edge case discovered in Chrome where the creation of multiple + // WebGL contexts would eventually lead to context creation failure. + // (crbug.com/319265) The test does not require that old contexts remain + // valid, only that new ones can be created. + function createContextCreationTest() { + return function() { + var canvas = document.createElement("canvas"); + canvas.width = 1; + canvas.height = 1; + + document.body.appendChild(canvas); + + var gl = wtu.create3DContext(canvas); + if (!gl) { + return false; + } + + gl.clear(gl.COLOR_BUFFER_BIT); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors"); + + return true; + }; + } + + // Draws rectangle on a passed canvas with preserveDrawingBuffer + // and antialiasing ON, tests rect color on every iteration. + function createMultisampleCorruptionTest(gl) { + var lastContext = null; + // Allocate a read back buffer in advance and reuse it for all iterations + // to avoid memory issues because of late garbage collection. + var readBackBuf = new Uint8Array(gl.canvas.width * gl.canvas.height * 4); + + var program = wtu.loadStandardProgram(gl); + var uniforms = wtu.getUniformMap(gl, program); + gl.useProgram(program); + + gl.clearColor(1.0, 0.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + + var vertexObject = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,2.5,0, 1.5,1.5,0, 2.5,1.5,0 ]), gl.STATIC_DRAW); + gl.enableVertexAttribArray(0); + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); + gl.vertexAttrib3f(1, 0.0, 0.0, 1.0); + + var identityMat = new Float32Array([ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ]); + + gl.uniformMatrix4fv(uniforms.u_modelViewProjMatrix.location, false, identityMat); + + function test() { + var gl2 = wtu.create3DContext(null, {antialias: true}); + + gl2.canvas.width = gl2.canvas.height = 1024; + gl2.canvas.style.width = gl2.canvas.style.height = "1px"; + document.body.appendChild(gl2.canvas); + + gl2.clearColor(1.0, 0.0, 0.0, 1.0); + gl2.clear(gl2.COLOR_BUFFER_BIT); + + if(lastContext) { + gl.drawArrays(gl.TRIANGLES, 0, 3); + var msg = "Canvas should be red"; + wtu.checkCanvasRectColor(gl, + 0, 0, gl.canvas.width, gl.canvas.height, + [255, 0, 0, 255], null, + function() { + testPassed(msg); + }, + function() { + testFailed(msg); + return false; + }, + debug, readBackBuf); + document.body.removeChild(lastContext.canvas); + } + + lastContext = gl2; + return true; + }; + + // First pass does initialization + test(); + + return test; + } + + return { + run: run, + + createContextCreationAndDestructionTest: createContextCreationAndDestructionTest, + createContextCreationTest: createContextCreationTest, + createMultisampleCorruptionTest: createMultisampleCorruptionTest + }; + +})(); diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/oes-texture-float-and-half-float-linear.js b/dom/canvas/test/webgl-conf/checkout/js/tests/oes-texture-float-and-half-float-linear.js new file mode 100644 index 000000000..7cc06312d --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/oes-texture-float-and-half-float-linear.js @@ -0,0 +1,183 @@ +/* +** Copyright (c) 2013 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. +*/ + +function generateTest(extensionTypeName, extensionName, pixelType, prologue) { + var wtu = WebGLTestUtils; + var gl = null; + var successfullyParsed = false; + + var init = function() + { + description("This test verifies the functionality of the " + extensionName + " extension, if it is available."); + + var canvas = document.getElementById("canvas"); + gl = wtu.create3DContext(canvas); + + if (!prologue(gl, extensionTypeName)) { + finishTest(); + return; + } + + // Before the extension is enabled + var extensionEnabled = false; + runTestSuite(extensionEnabled); + + if (!gl.getExtension(extensionName)) + testPassed("No " + extensionName + " support -- this is legal"); + else { + // After the extension is enabled + extensionEnabled = true; + runTestSuite(extensionEnabled); + } + + finishTest(); + } + + function runTestSuite(extensionEnabled) + { + var magF = [gl.NEAREST, gl.LINEAR]; + var minF = [gl.NEAREST, gl.LINEAR, gl.NEAREST_MIPMAP_NEAREST, gl.NEAREST_MIPMAP_LINEAR, gl.LINEAR_MIPMAP_NEAREST, gl.LINEAR_MIPMAP_LINEAR]; + var tex2DFShader = [ + 'uniform sampler2D tex;', + 'void main() {', + ' gl_FragData[0] = texture2D(tex, vec2(0.5, 0.5)) * vec4(4.0, 2.0, 2.0, 1);', + '}'].join('\n'); + + var positionVertexShader = [ + 'attribute vec4 vPosition;', + 'void main() {', + ' gl_Position = vPosition;', + '}'].join('\n'); + + var texCubeFShader = [ + 'uniform samplerCube tex;', + 'void main() {', + ' gl_FragColor = textureCube(tex, normalize(vec3(0.5, 0.5, 1))) * vec4(4.0, 2.0, 2.0, 1);', + '}'].join('\n'); + + var vs = wtu.loadShader(gl, positionVertexShader, gl.VERTEX_SHADER); + var fs_2d = wtu.loadShader(gl, tex2DFShader, gl.FRAGMENT_SHADER); + var fs_cube = wtu.loadShader(gl, texCubeFShader, gl.FRAGMENT_SHADER); + + // TEXTURE_2D + var program = wtu.setupProgram(gl, [vs, fs_2d]); + gl.useProgram(program); + wtu.setupUnitQuad(gl); + for (var kk = 0; kk < 2; ++kk) { + for (var ii = 0; ii < 6; ++ii) { + var linear = false; + if (magF[kk] == gl.LINEAR || (minF[ii] != gl.NEAREST && minF[ii] != gl.NEAREST_MIPMAP_NEAREST)) + linear = true; + var color = (!extensionEnabled && linear) ? [0, 0, 0, 255] : [255, 255, 255, 255]; + runEachTest(gl.TEXTURE_2D, magF[kk], minF[ii], linear, extensionEnabled, color); + } + } + + // TEXTURE_CUBE_MAP + var programCube = wtu.setupProgram(gl, [vs, fs_cube]); + gl.useProgram(programCube); + wtu.setupUnitQuad(gl); + for (var kk = 0; kk < 2; ++kk) { + for (var ii = 0; ii < 6; ++ii) { + var linear = false; + if (magF[kk] == gl.LINEAR || (minF[ii] != gl.NEAREST && minF[ii] != gl.NEAREST_MIPMAP_NEAREST)) + linear = true; + var color = (!extensionEnabled && linear) ? [0, 0, 0, 255] : [255, 255, 255, 255]; + runEachTest(gl.TEXTURE_CUBE_MAP, magF[kk], minF[ii], linear, extensionEnabled, color); + } + } + } + + function runEachTest(textureTarget, magFilter, minFilter, linear, extensionEnabled, expected) + { + var format = gl.RGBA; + var numberOfChannels = 4; + debug(""); + debug("testing target: " + wtu.glEnumToString(gl,textureTarget) + + ", testing format: " + wtu.glEnumToString(gl, format) + + ", magFilter is: " + wtu.glEnumToString(gl, magFilter) + + ", minFilter is: " + wtu.glEnumToString(gl, minFilter) + + ", " + extensionName + " is " + (extensionEnabled ? "enabled": "not enabled") + ); + + // Generate data. + var width = 4; + var height = 4; + var canvas2d = document.createElement('canvas'); + canvas2d.width = width; + canvas2d.height = height; + var ctx2d = canvas2d.getContext('2d'); + var color = [64, 128, 128, 255]; + ctx2d.fillStyle = "rgba(" + color[0] + "," + color[1] + "," + color[2] + "," + color[3] + ")"; + ctx2d.fillRect(0, 0, width, height); + + var texture = gl.createTexture(); + gl.bindTexture(textureTarget, texture); + gl.texParameteri(textureTarget, gl.TEXTURE_MAG_FILTER, magFilter); + gl.texParameteri(textureTarget, gl.TEXTURE_MIN_FILTER, minFilter); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(textureTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + if (textureTarget == gl.TEXTURE_2D) { + gl.texImage2D(gl.TEXTURE_2D, 0, format, format, gl[pixelType], canvas2d); + if (minFilter != gl.NEAREST && minFilter != gl.LINEAR) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors during texture setup"); + gl.generateMipmap(gl.TEXTURE_2D); + if (gl.getError() != gl.NO_ERROR) { + debug("generateMipmap failed for floating-point TEXTURE_2D -- this is legal -- skipping the rest of this test"); + return; + } + } + } else if (textureTarget == gl.TEXTURE_CUBE_MAP) { + var targets = [ + gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; + for (var tt = 0; tt < targets.length; ++tt) + gl.texImage2D(targets[tt], 0, format, format, gl[pixelType], canvas2d); + if (minFilter != gl.NEAREST && minFilter != gl.LINEAR) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors during texture setup"); + gl.generateMipmap(gl.TEXTURE_CUBE_MAP); + if (gl.getError() != gl.NO_ERROR) { + debug("generateMipmap failed for floating-point TEXTURE_CUBE_MAP -- this is legal -- skipping the rest of this test"); + return; + } + } + } + wtu.clearAndDrawUnitQuad(gl); + if (!linear) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, extensionTypeName + " texture with non-Linear filter should succeed with NO_ERROR no matter whether " + extensionName + " is enabled or not"); + } else if (!extensionEnabled) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, extensionTypeName + " texture with Linear filter should produce [0, 0, 0, 1.0] with NO_ERROR if " + extensionName + " isn't enabled"); + } else { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, extensionTypeName + " texture with Linear filter should succeed with NO_ERROR if " + extensionTypeName + " is enabled"); + } + + wtu.checkCanvas(gl, expected, "should be " + expected[0] + "," + expected[1] + "," + expected[2] + "," + expected[3]); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/out-of-bounds-test.js b/dom/canvas/test/webgl-conf/checkout/js/tests/out-of-bounds-test.js new file mode 100644 index 000000000..69846cda0 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/out-of-bounds-test.js @@ -0,0 +1,343 @@ +/* +** Copyright (c) 2014 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. +*/ + +'use strict'; + +var OutOfBoundsTest = (function() { + +var runCommonInvalidValueTests = function(callTemplate, gl, wtu, ext) { + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: -1, type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: -1})); + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: -1, type: 'gl.UNSIGNED_BYTE', offset: 1})); + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: 1, type: 'gl.UNSIGNED_BYTE', offset: -1})); + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: '0xffffffff', type: 'gl.UNSIGNED_BYTE', offset: 0})); +}; + +var setupProgramAndBindVertexArray = function(gl, wtu) { + var program = wtu.loadStandardProgram(gl); + + gl.useProgram(program); + var vertexObject = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); + gl.enableVertexAttribArray(0); + + return program; +}; + +var setupProgram2 = function(gl, wtu) { + var vshader = [ + 'attribute vec3 aOne;', + 'attribute vec2 aTwo;', + 'void main() {', + ' gl_Position = vec4(aOne, 1.0) + vec4(aTwo, 0.0, 1.0);', + '}' + ].join('\n'); + + var fshader = [ + 'void main() {', + ' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);', + '}' + ].join('\n'); + + var program = wtu.setupProgram(gl, [vshader, fshader], [ "aOne", "aTwo" ]); + if (!program) { + testFailed("failed to create test program"); + } + return program; +}; + +var runDrawArraysTest = function(callTemplate, gl, wtu, ext) { + var program = setupProgramAndBindVertexArray(gl, wtu); + + debug("Test empty buffer") + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ ]), gl.STATIC_DRAW); + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 1})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 10000})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 10000000000000})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 1, count: 0})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 0})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 100, count: 0})); + runCommonInvalidValueTests(callTemplate, gl, wtu, ext); + + debug("") + debug("Test buffer with 3 float vectors") + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW); + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 3})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 3, count: 2})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 10000})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 10000000000000})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 0})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 100, count: 0})); + runCommonInvalidValueTests(callTemplate, gl, wtu, ext); + + debug("") + debug("Test buffer with interleaved (3+2) float vectors") + + setupProgram2(gl, wtu); + + var vbo = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vbo); + // enough for 9 vertices, so 3 triangles + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(9*5), gl.STATIC_DRAW); + + // bind first 3 elements, with a stride of 5 float elements + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 5*4, 0); + // bind 2 elements, starting after the first 3; same stride of 5 float elements + gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 5*4, 3*4); + + gl.enableVertexAttribArray(0); + gl.enableVertexAttribArray(1); + + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9})); + + // negative values must generate INVALID_VALUE; they can never be valid + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: 0, count: -500})); + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: -200, count: 1})); + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: -200, count: -500})); + + // 0xffffffff needs to convert to a 'long' IDL argument as -1, as per + // WebIDL 4.1.7. JS ToInt32(0xffffffff) == -1. Thus INVALID_VALUE. + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: 0, count: '0xffffffff'})); + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: '0xffffffff', count: '0xffffffff'})); + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: '0xffffffff', count: 1})); + + // values that could otherwise be valid but aren't due to bindings generate + // INVALID_OPERATION + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 200})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: '0x7fffffff'})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: '0x7fffffff', count: 1})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: '0x7fffffff', count: '0x7fffffff'})); +}; + +var runDrawElementsTest = function(callTemplate, gl, wtu, ext) { + var program = setupProgramAndBindVertexArray(gl, wtu); + var contextVersion = wtu.getDefault3DContextVersion(); + + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW); + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); + + var indexObject = gl.createBuffer(); + + debug('Test empty index buffer'); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ ]), gl.STATIC_DRAW); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 10000, type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 10000000000000, type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 1, type: 'gl.UNSIGNED_BYTE', offset: 0})); + runCommonInvalidValueTests(callTemplate, gl, wtu, ext); + + debug(''); + debug('Test buffer with 3 byte indexes'); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexObject); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2 ]), gl.STATIC_DRAW); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 2})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 10000, type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 10000000000000, type: 'gl.UNSIGNED_BYTE', offset: 0})); + runCommonInvalidValueTests(callTemplate, gl, wtu, ext); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 4})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: '0x7fffffff', type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: '0x7fffffff', type: 'gl.UNSIGNED_BYTE', offset: '0x7fffffff'})); + + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, (new Uint8Array([ 3, 0, 1, 2 ])).subarray(1), gl.STATIC_DRAW)'); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint8Array([ 3, 0, 1]))'); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, (new Uint8Array([ 3, 0, 1, 2 ])).subarray(1))'); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 0})); + + debug(''); + debug('Test buffer with interleaved (3+2) float vectors'); + + setupProgram2(gl, wtu); + + var vbo = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vbo); + // enough for 9 vertices, so 3 triangles + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(9*5), gl.STATIC_DRAW); + + // bind first 3 elements, with a stride of 5 float elements + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 5*4, 0); + // bind 2 elements, starting after the first 3; same stride of 5 float elements + gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 5*4, 3*4); + + gl.enableVertexAttribArray(0); + gl.enableVertexAttribArray(1); + + var ebo = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo); + // For WebGL 2, PRIMITIVE_RESTART_FIXED_INDEX is always enabled. + // 0xffff will be handled as a primitive restart. + if (contextVersion <= 1) { + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( + [ 0, 1, 2, + 1, 2, 0, + 2, 0, 1, + 201, 202, 203, + 0x7fff, 0x7fff, 0x7fff, + 0xffff, 0xffff, 0xffff ]), + gl.STATIC_DRAW); + } else { + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( + [ 0, 1, 2, + 1, 2, 0, + 2, 0, 1, + 201, 202, 203, + 0x7fff, 0x7fff, 0x7fff, + 0xffff - 1, 0xffff - 1, 0xffff - 1 ]), + gl.STATIC_DRAW); + } + + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 9, type: 'gl.UNSIGNED_SHORT', offset: 0})); + + + // invalid operation with indices that would be valid with correct bindings + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 9, type: 'gl.UNSIGNED_SHORT', offset: 1000})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 12, type: 'gl.UNSIGNED_SHORT', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 15, type: 'gl.UNSIGNED_SHORT', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 18, type: 'gl.UNSIGNED_SHORT', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_SHORT', offset: 2*15})); + + // 0xffffffff needs to convert to a 'long' IDL argument as -1, as per + // WebIDL 4.1.7. JS ToInt32(0xffffffff) == -1. Thus INVALID_VALUE. + wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: '0xffffffff', type: 'gl.UNSIGNED_SHORT', offset: 0})); + // offset is defined as GLintptr, which is long long in IDL (64-bit). + // 2^32 - 1 should not overflow, and only result in INVALID_OPERATION. + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 1, type: 'gl.UNSIGNED_SHORT', offset: '0xffffffff'})); + + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: '0x7fffffff', type: 'gl.UNSIGNED_SHORT', offset: 0})); + + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_SHORT', offset: 0})); + + // invalid operation with offset that's not a multiple of the type size + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 1})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 2})); + + // invalid operation if no buffer is bound to ELEMENT_ARRAY_BUFFER + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 0})); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo); + + debug(''); + debug('Test buffer setting attrib 0 to a buffer too small and disable it.'); + var smallVBO = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, smallVBO); + gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW); + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0x10); + gl.disableVertexAttribArray(0); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 2})); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 2})); +}; + +var runInstancedTest = function(callTemplate, gl, wtu, ext) { + setupProgram2(gl, wtu); + + // Initialize non-instanced attribute data. + // Enough for 9 vertices, so 3 triangles. + var vbo = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vbo); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(9*3), gl.STATIC_DRAW); + + gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); + + // Setup buffer for instanced attribute data. + var vbo2 = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vbo2); + gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0); + + gl.enableVertexAttribArray(0); + gl.enableVertexAttribArray(1); + + debug('Test out-of-range instanced attributes'); + debug(''); + + debug('Test with an empty buffer for the instanced attribute'); + ext.vertexAttribDivisorANGLE(1, 1); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 0})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 10000, primcount: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 1})); + + debug('Test with a buffer with 1 float for the instanced attribute'); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(1), gl.STATIC_DRAW); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 0})); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 10000, primcount: 0})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 1})); + + debug(''); + debug('Test with a buffer with 2 floats for the instanced attribute'); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(2), gl.STATIC_DRAW); + debug('Divisor 1'); + ext.vertexAttribDivisorANGLE(1, 1); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 1})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 2})); + debug('Divisor 3'); + ext.vertexAttribDivisorANGLE(1, 3); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 3})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 4})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 10000})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: '0x7fffffff'})); + + debug(''); + debug('Test with a buffer with 4 floats for the instanced attribute'); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(4), gl.STATIC_DRAW); + debug('Divisor 1'); + ext.vertexAttribDivisorANGLE(1, 1); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 2})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 3})); + debug('Divisor 2'); + ext.vertexAttribDivisorANGLE(1, 2); + wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 4})); + wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 5})); +}; + +var runDrawArraysInstancedTest = function(callTemplate, gl, wtu, ext) { + runInstancedTest(callTemplate, gl, wtu, ext); +}; + +var runDrawElementsInstancedTest = function(callTemplate, gl, wtu, ext) { + var ebo = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array( + [ 0, 1, 2, + 5, 4, 3, + 6, 7, 8 ]), + gl.STATIC_DRAW); + callTemplate = wtu.replaceParams(callTemplate, {type: 'gl.UNSIGNED_BYTE', offset: '$(offset)', count: '$(count)', primcount: '$(primcount)'}); + runInstancedTest(callTemplate, gl, wtu, ext); +}; + +return { + runDrawArraysTest: runDrawArraysTest, + runDrawArraysInstancedTest: runDrawArraysInstancedTest, + runDrawElementsTest: runDrawElementsTest, + runDrawElementsInstancedTest: runDrawElementsInstancedTest +}; + +})(); diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js new file mode 100644 index 000000000..33ab722d4 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas-sub-rectangle.js @@ -0,0 +1,329 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var realRedColor = [255, 0, 0]; + var realGreenColor = [0, 255, 0]; + var realBlueColor = [0, 0, 255]; + var realCyanColor = [0, 255, 255]; + var redColor = realRedColor; + var greenColor = realGreenColor; + var blueColor = realBlueColor; + var cyanColor = realCyanColor; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking a sub-rectangle of a canvas (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + + // The sub-rectangle tests only apply to WebGL 2.0 for the + // time being, though the tests for the WebGL 1.0 + // format/internal format/type combinations are generated into + // conformance/textures/. + if (wtu.getDefault3DContextVersion() < 2) { + debug('Test only applies to WebGL 2.0'); + finishTest(); + return; + } + + gl = wtu.create3DContext("example", { preserveDrawingBuffer: true }); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + blueColor = [0, 0, 0]; + cyanColor = [0, 0, 0]; + break; + + case gl.RG: + case gl.RG_INTEGER: + blueColor = [0, 0, 0]; + cyanColor = [0, 255, 0]; + break; + + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + gl.disable(gl.BLEND); + + var canvas2d = document.createElement('canvas'); + runTest(canvas2d, setupSourceCanvas2D, '2D-rendered canvas'); + + var canvasWebGL = document.createElement('canvas'); + runTest(canvasWebGL, setupSourceCanvasWebGL, 'WebGL-rendered canvas'); + + finishTest(); + } + + function fillStyle2D(ctx, color) { + ctx.fillStyle = 'rgb(' + color[0] + ', ' + color[1] + ', ' + color[2] + ')'; + } + + function setupSourceCanvas2D(canvas) { + var width = canvas.width; + var height = canvas.height; + var halfWidth = Math.floor(width / 2); + var halfHeight = Math.floor(height / 2); + + var ctx = canvas.getContext('2d'); + // Always use the same pattern for this test: four quadrants: + // red green + // blue cyan + // Handle odd-sized canvases + fillStyle2D(ctx, realRedColor); + ctx.fillRect(0, 0, halfWidth, halfHeight); + fillStyle2D(ctx, realGreenColor); + ctx.fillRect(halfWidth, 0, width - halfWidth, halfHeight); + fillStyle2D(ctx, realBlueColor); + ctx.fillRect(0, halfHeight, halfWidth, height - halfHeight); + fillStyle2D(ctx, realCyanColor); + ctx.fillRect(halfWidth, halfHeight, width - halfWidth, height - halfHeight); + } + + function clearColorWebGL(ctx, color) { + ctx.clearColor(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0, 1.0); + ctx.clear(ctx.COLOR_BUFFER_BIT); + } + + function setupSourceCanvasWebGL(canvas) { + var width = canvas.width; + var height = canvas.height; + var halfWidth = Math.floor(width / 2); + var halfHeight = Math.floor(height / 2); + + var ctx = canvas.getContext('webgl'); + // Always use the same pattern for this test: four quadrants: + // red green + // blue cyan + // Handle odd-sized canvases + + ctx.viewport(0, 0, width, height); + ctx.enable(ctx.SCISSOR_TEST); + // OpenGL origin is lower-left + ctx.scissor(0, 0, halfWidth, halfHeight); + clearColorWebGL(ctx, realBlueColor); + ctx.scissor(halfWidth, 0, width - halfWidth, halfHeight); + clearColorWebGL(ctx, realCyanColor); + ctx.scissor(0, halfHeight, halfWidth, height - halfHeight); + clearColorWebGL(ctx, realRedColor); + ctx.scissor(halfWidth, halfHeight, width - halfWidth, height - halfHeight); + clearColorWebGL(ctx, realGreenColor); + } + + function runOneIteration(sourceDescription, useTexSubImage2D, flipY, + canvas, canvasSize, canvasSetupFunction, + sourceSubRectangle, expected, + bindingTarget, program) + { + sourceSubRectangleString = ''; + if (sourceSubRectangle) { + sourceSubRectangleString = ', sourceSubRectangle=' + sourceSubRectangle; + } + debug(''); + debug('Testing ' + sourceDescription + ' with ' + + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + + ', flipY=' + flipY + + ', bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') + + sourceSubRectangleString); + + var loc; + var skipCorner = false; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + loc = gl.getUniformLocation(program, "face"); + switch (gl[pixelFormat]) { + case gl.RED_INTEGER: + case gl.RG_INTEGER: + case gl.RGB_INTEGER: + case gl.RGBA_INTEGER: + // https://github.com/KhronosGroup/WebGL/issues/1819 + skipCorner = true; + break; + } + } + + if (skipCorner && sourceSubRectangle && + sourceSubRectangle[2] == 1 && sourceSubRectangle[3] == 1) { + debug("Test skipped, see WebGL#1819"); + return; + } + + // Initialize the contents of the source canvas. + var width = canvasSize[0]; + var height = canvasSize[1]; + var halfWidth = Math.floor(width / 2); + var halfHeight = Math.floor(height / 2); + canvas.width = width; + canvas.height = height; + canvasSetupFunction(canvas); + + // Upload the source canvas to the texture and draw it to a quad. + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Enable writes to the RGBA channels + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);'); + var targets = [gl.TEXTURE_2D]; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; + } + // In this test, this is always specified. It's currently WebGL 2.0-specific. + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); + // Upload the image into the texture + var uploadWidth = sourceSubRectangle[2]; + var uploadHeight = sourceSubRectangle[3]; + for (var tt = 0; tt < targets.length; ++tt) { + if (useTexSubImage2D) { + // Initialize the texture to black first + gl.texImage2D(targets[tt], 0, gl[internalFormat], + uploadWidth, uploadHeight, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, + uploadWidth, uploadHeight, + gl[pixelFormat], gl[pixelType], canvas); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], + uploadWidth, uploadHeight, 0, + gl[pixelFormat], gl[pixelType], canvas); + } + } + + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + + // The tests are constructed to upload a single solid color + // out of the canvas. + var outputCanvasWidth = gl.drawingBufferWidth; + var outputCanvasHeight = gl.drawingBufferHeight; + var outputCanvasHalfWidth = Math.floor(outputCanvasWidth / 2); + var outputCanvasHalfHeight = Math.floor(outputCanvasHeight / 2); + var top = 0; + var bottom = outputCanvasHeight - outputCanvasHalfHeight; + var left = 0; + var right = outputCanvasWidth - outputCanvasHalfWidth; + + for (var tt = 0; tt < targets.length; ++tt) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + gl.uniform1i(loc, targets[tt]); + } + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + + // Check the four quadrants and make sure they have the right color. + // This is split up into four tests only because of the driver bug above. + var msg = 'should be ' + expected; + wtu.checkCanvasRect(gl, left, top, outputCanvasHalfWidth, outputCanvasHalfHeight, expected, msg); + if (!skipCorner) { + wtu.checkCanvasRect(gl, right, top, outputCanvasHalfWidth, outputCanvasHalfHeight, expected, msg); + } + wtu.checkCanvasRect(gl, left, bottom, outputCanvasHalfWidth, outputCanvasHalfHeight, expected, msg); + if (!skipCorner) { + wtu.checkCanvasRect(gl, right, bottom, outputCanvasHalfWidth, outputCanvasHalfHeight, expected, msg); + } + } + } + + function runTest(canvas, canvasSetupFunction, sourceDescription) + { + var program = tiu.setupTexturedQuad(gl, internalFormat); + runTestOnBindingTarget(gl.TEXTURE_2D, program, canvas, canvasSetupFunction, sourceDescription); + program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); + runTestOnBindingTarget(gl.TEXTURE_CUBE_MAP, program, canvas, canvasSetupFunction, sourceDescription); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + } + + function runTestOnBindingTarget(bindingTarget, program, canvas, canvasSetupFunction, sourceDescription) { + var cases = [ + // Small canvas cases. Expected that these won't be + // GPU-accelerated in most browsers' implementations. + { expected: redColor, flipY: false, size: [2, 2], subRect: [0, 0, 1, 1] }, + { expected: greenColor, flipY: false, size: [2, 2], subRect: [1, 0, 1, 1] }, + { expected: blueColor, flipY: false, size: [2, 2], subRect: [0, 1, 1, 1] }, + { expected: cyanColor, flipY: false, size: [2, 2], subRect: [1, 1, 1, 1] }, + { expected: redColor, flipY: true, size: [2, 2], subRect: [0, 1, 1, 1] }, + { expected: greenColor, flipY: true, size: [2, 2], subRect: [1, 1, 1, 1] }, + { expected: blueColor, flipY: true, size: [2, 2], subRect: [0, 0, 1, 1] }, + { expected: cyanColor, flipY: true, size: [2, 2], subRect: [1, 0, 1, 1] }, + + // Larger canvas cases. Expected that these will be + // GPU-accelerated in most browsers' implementations. + // Changes will be gladly accepted to trigger more + // browsers' heuristics to accelerate these canvases. + { expected: redColor, flipY: false, size: [384, 384], subRect: [ 0, 0, 192, 192] }, + { expected: greenColor, flipY: false, size: [384, 384], subRect: [192, 0, 192, 192] }, + { expected: blueColor, flipY: false, size: [384, 384], subRect: [ 0, 192, 192, 192] }, + { expected: cyanColor, flipY: false, size: [384, 384], subRect: [192, 192, 192, 192] }, + { expected: blueColor, flipY: true, size: [384, 384], subRect: [ 0, 0, 192, 192] }, + { expected: cyanColor, flipY: true, size: [384, 384], subRect: [192, 0, 192, 192] }, + { expected: redColor, flipY: true, size: [384, 384], subRect: [ 0, 192, 192, 192] }, + { expected: greenColor, flipY: true, size: [384, 384], subRect: [192, 192, 192, 192] }, + + ]; + + for (var i in cases) { + runOneIteration(sourceDescription, false, cases[i].flipY, + canvas, cases[i].size, canvasSetupFunction, + cases[i].subRect, + cases[i].expected, bindingTarget, program); + + // In Chrome, this hits a bug on Mac with Intel GPU. + // Chromium bug: crbug.com/665656 + // Apple Radar: 29563996 + //runOneIteration(sourceDescription, true, cases[i].flipY, + // canvas, cases[i].size, canvasSetupFunction, + // cases[i].subRect, + // cases[i].expected, bindingTarget, program); + } + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas.js new file mode 100644 index 000000000..4024a0200 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-canvas.js @@ -0,0 +1,320 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var whiteColor = [255, 255, 255, 255]; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking canvas elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + whiteColor = [255, 0, 0, 255]; + greenColor = [0, 0, 0]; + break; + case gl.RG: + case gl.RG_INTEGER: + whiteColor = [255, 255, 0, 255]; + break; + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + var testCanvas = document.createElement('canvas'); + runTest(testCanvas); + //document.body.appendChild(testCanvas); + } + + function setCanvasToRedGreen(ctx) { + var width = ctx.canvas.width; + var height = ctx.canvas.height; + var halfHeight = Math.floor(height / 2); + ctx.fillStyle = "#ff0000"; + ctx.fillRect(0, 0, width, halfHeight); + ctx.fillStyle = "#00ff00"; + ctx.fillRect(0, halfHeight, width, height - halfHeight); + } + + function drawTextInCanvas(ctx, bindingTarget) { + var width = ctx.canvas.width; + var height = ctx.canvas.height; + ctx.fillStyle = "#ffffff"; + ctx.fillRect(0, 0, width, height); + ctx.font = '20pt Arial'; + ctx.fillStyle = 'black'; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillText("1234567890", width / 2, height / 4); + } + + function setCanvasTo257x257(ctx, bindingTarget) { + ctx.canvas.width = 257; + ctx.canvas.height = 257; + setCanvasToRedGreen(ctx); + } + + function setCanvasToMin(ctx, bindingTarget) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + // cube map texture must be square. + ctx.canvas.width = 2; + } else { + ctx.canvas.width = 1; + } + ctx.canvas.height = 2; + setCanvasToRedGreen(ctx); + } + + function checkSourceCanvasImageData(imageDataBefore, imageDataAfter) { + if (imageDataBefore.length != imageDataAfter.length) { + testFailed("The size of image data in source canvas become different after it is used in webgl texture."); + return; + } + for (var i = 0; i < imageDataAfter.length; i++) { + if (imageDataBefore[i] != imageDataAfter[i]) { + testFailed("Pixel values in source canvas have changed after canvas used in webgl texture."); + return; + } + } + testPassed("Pixel values in source canvas remain unchanged after canvas used in webgl texture."); + } + + function runOneIteration(canvas, useTexSubImage2D, flipY, program, bindingTarget, opt_texture, opt_fontTest) + { + debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + + ' with flipY=' + flipY + ' bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') + + ' canvas size: ' + canvas.width + 'x' + canvas.height + + (opt_fontTest ? " with fonts" : " with red-green")); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + if (!opt_texture) { + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } else { + var texture = opt_texture; + } + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);'); + var targets = [gl.TEXTURE_2D]; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; + } + // Upload the image into the texture + for (var tt = 0; tt < targets.length; ++tt) { + // Initialize the texture to black first + if (useTexSubImage2D) { + gl.texImage2D(targets[tt], 0, gl[internalFormat], canvas.width, canvas.height, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], canvas); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], canvas); + } + } + + var width = gl.canvas.width; + var height = gl.canvas.height; + var halfWidth = Math.floor(width / 2); + var halfHeight = Math.floor(height / 2); + var top = flipY ? 0 : (height - halfHeight); + var bottom = flipY ? (height - halfHeight) : 0; + + var loc; + var skipCorner = false; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + loc = gl.getUniformLocation(program, "face"); + switch (gl[pixelFormat]) { + case gl.RED_INTEGER: + case gl.RG_INTEGER: + case gl.RGB_INTEGER: + case gl.RGBA_INTEGER: + // https://github.com/KhronosGroup/WebGL/issues/1819 + skipCorner = true; + break; + } + } + + for (var tt = 0; tt < targets.length; ++tt) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + gl.uniform1i(loc, targets[tt]); + } + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]); + + if (opt_fontTest) { + // check half is a solid color. + wtu.checkCanvasRect( + gl, 0, top, width, halfHeight, + whiteColor, + "should be white"); + // check other half is not a solid color. + wtu.checkCanvasRectColor( + gl, 0, bottom, width, halfHeight, + whiteColor, 0, + function() { + testFailed("font missing"); + }, + function() { + testPassed("font rendered"); + }, + debug); + } else { + // Check the top and bottom halves and make sure they have the right color. + debug("Checking " + (flipY ? "top" : "bottom")); + wtu.checkCanvasRect(gl, 0, bottom, (skipCorner && flipY) ? halfWidth : width, halfHeight, redColor, + "shouldBe " + redColor); + debug("Checking " + (flipY ? "bottom" : "top")); + wtu.checkCanvasRect(gl, 0, top, (skipCorner && !flipY) ? halfWidth : width, halfHeight, greenColor, + "shouldBe " + greenColor); + } + + if (!useTexSubImage2D && pixelFormat == "RGBA") { + if (pixelType == "FLOAT") { + // Attempt to set a pixel in the texture to ensure the texture was + // actually created with floats. Regression test for http://crbug.com/484968 + var pixels = new Float32Array([1000.0, 1000.0, 1000.0, 1000.0]); + gl.texSubImage2D(targets[tt], 0, 0, 0, 1, 1, gl[pixelFormat], gl[pixelType], pixels); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Texture should be backed by floats"); + } else if (pixelType == "HALF_FLOAT_OES" || pixelType == "HALF_FLOAT") { + // Attempt to set a pixel in the texture to ensure the texture was + // actually created with half-floats. Regression test for http://crbug.com/484968 + var halfFloatTenK = 0x70E2; // Half float 10000 + var pixels = new Uint16Array([halfFloatTenK, halfFloatTenK, halfFloatTenK, halfFloatTenK]); + gl.texSubImage2D(targets[tt], 0, 0, 0, 1, 1, gl[pixelFormat], gl[pixelType], pixels); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Texture should be backed by half-floats"); + } + } + } + + if (false) { + var m = wtu.makeImageFromCanvas(gl.canvas); + document.getElementById("console").appendChild(m); + document.getElementById("console").appendChild(document.createElement("hr")); + } + + return texture; + } + + function runTest(canvas) + { + var ctx = canvas.getContext("2d"); + + var cases = [ + { sub: false, flipY: true, font: false, init: setCanvasToMin }, + { sub: false, flipY: false, font: false }, + { sub: true, flipY: true, font: false }, + { sub: true, flipY: false, font: false }, + { sub: false, flipY: true, font: false, init: setCanvasTo257x257 }, + { sub: false, flipY: false, font: false }, + { sub: true, flipY: true, font: false }, + { sub: true, flipY: false, font: false }, + { sub: false, flipY: true, font: true, init: drawTextInCanvas }, + { sub: false, flipY: false, font: true }, + { sub: true, flipY: true, font: true }, + { sub: true, flipY: false, font: true }, + ]; + + function runTexImageTest(bindingTarget) { + var program; + if (bindingTarget == gl.TEXTURE_2D) { + program = tiu.setupTexturedQuad(gl, internalFormat); + } else { + program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); + } + + return new Promise(function(resolve, reject) { + var count = 4; + var caseNdx = 0; + var texture = undefined; + function runNextTest() { + var c = cases[caseNdx]; + var imageDataBefore = null; + if (c.init) { + c.init(ctx, bindingTarget); + imageDataBefore = ctx.getImageData(0, 0, canvas.width, canvas.height); + } + texture = runOneIteration(canvas, c.sub, c.flipY, program, bindingTarget, texture, c.font); + if (c.init) { + debug("Checking if pixel values in source canvas change after canvas used as webgl texture"); + checkSourceCanvasImageData(imageDataBefore, ctx.getImageData(0, 0, canvas.width, canvas.height)); + } + // for the first 2 iterations always make a new texture. + if (count > 2) { + gl.deleteTexture(texture); + texture = undefined; + } + ++caseNdx; + if (caseNdx == cases.length) { + caseNdx = 0; + --count; + if (!count) { + resolve("SUCCESS"); + return; + } + } + wtu.waitForComposite(runNextTest); + } + runNextTest(); + }); + } + + runTexImageTest(gl.TEXTURE_2D).then(function(val) { + runTexImageTest(gl.TEXTURE_CUBE_MAP).then(function(val) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + }); + }); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js new file mode 100644 index 000000000..2b8d04740 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-blob.js @@ -0,0 +1,63 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from a Blob (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + var xhr = new XMLHttpRequest(); + xhr.open("GET", resourcePath + "red-green-semi-transparent.png"); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + var blob = xhr.response; + runImageBitmapTest(blob, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false); + finishTest(); + } + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js new file mode 100644 index 000000000..98ec219c9 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-canvas.js @@ -0,0 +1,89 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from an HTMLCanvasElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + var testCanvas = document.createElement('canvas'); + var ctx = testCanvas.getContext("2d"); + setCanvasToMin(ctx); + runImageBitmapTest(testCanvas, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false); + + setCanvasTo257x257(ctx); + runImageBitmapTest(testCanvas, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false); + finishTest(); + } + + function setCanvasToRedGreen(ctx) { + var width = ctx.canvas.width; + var halfWidth = Math.floor(width / 2); + var height = ctx.canvas.height; + var halfHeight = Math.floor(height / 2); + ctx.fillStyle = "rgba(255, 0, 0, 1)"; + ctx.fillRect(0, 0, halfWidth, halfHeight); + ctx.fillStyle = "rgba(255, 0, 0, 0.5)"; + ctx.fillRect(halfWidth, 0, halfWidth, halfHeight); + ctx.fillStyle = "rgba(0, 255, 0, 1)"; + ctx.fillRect(0, halfHeight, halfWidth, halfHeight); + ctx.fillStyle = "rgba(0, 255, 0, 0.5)"; + ctx.fillRect(halfWidth, halfHeight, halfWidth, halfHeight); + } + + function setCanvasToMin(ctx) { + ctx.canvas.width = 2; + ctx.canvas.height = 2; + setCanvasToRedGreen(ctx); + } + + function setCanvasTo257x257(ctx) { + ctx.canvas.width = 257; + ctx.canvas.height = 257; + setCanvasToRedGreen(ctx); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js new file mode 100644 index 000000000..6c07b5dbe --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-bitmap.js @@ -0,0 +1,67 @@ +/* +** Copyright (c) 2015 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from an ImageBitmap (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + gl.disable(gl.BLEND); + + var imageData = new ImageData(new Uint8ClampedArray( + [255, 0, 0, 255, + 255, 0, 0, 0, + 0, 255, 0, 255, + 0, 255, 0, 0]), + 2, 2); + + createImageBitmap(imageData, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(bitmap) { + // bitmap is in unpremultiplied form + runImageBitmapTest(bitmap, 0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false); + finishTest(); + }); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js new file mode 100644 index 000000000..1c26db6ef --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image-data.js @@ -0,0 +1,64 @@ +/* +** Copyright (c) 2015 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from ImageData (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + gl.disable(gl.BLEND); + + var imageData = new ImageData(new Uint8ClampedArray( + [255, 0, 0, 255, + 255, 0, 0, 0, + 0, 255, 0, 255, + 0, 255, 0, 0]), + 2, 2); + + runImageBitmapTest(imageData, 0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false); + finishTest(); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js new file mode 100644 index 000000000..e242b8606 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-image.js @@ -0,0 +1,61 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from an HTMLImageElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + var image = new Image(); + image.onload = function() { + bufferedLogToConsole("Source image has been loaded"); + runImageBitmapTest(image, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false); + finishTest(); + } + image.src = resourcePath + "red-green-semi-transparent.png"; + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js new file mode 100644 index 000000000..1ef2dabe2 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-bitmap-from-video.js @@ -0,0 +1,61 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking ImageBitmap created from an HTMLVideoElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + var video = document.createElement("video"); + video.oncanplaythrough = function() { + runImageBitmapTest(video, 1, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, false); + finishTest(); + } + video.src = resourcePath + "red-green.theora.ogv"; + document.body.appendChild(video); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-data.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-data.js new file mode 100644 index 000000000..80abb697c --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image-data.js @@ -0,0 +1,267 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var imageData = null; + var blackColor = [0, 0, 0]; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking ImageData (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + break; + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + gl.disable(gl.BLEND); + + var canvas2d = document.getElementById("texcanvas"); + var context2d = canvas2d.getContext("2d"); + imageData = context2d.createImageData(2, 2); + var data = imageData.data; + data[0] = 255; + data[1] = 0; + data[2] = 0; + data[3] = 255; + data[4] = 255; + data[5] = 0; + data[6] = 0; + data[7] = 0; + data[8] = 0; + data[9] = 255; + data[10] = 0; + data[11] = 255; + data[12] = 0; + data[13] = 255; + data[14] = 0; + data[15] = 0; + + runTest(); + } + + function runOneIteration(useTexSubImage2D, flipY, premultiplyAlpha, + sourceSubRectangle, expected, + bindingTarget, program) + { + sourceSubRectangleString = ''; + if (sourceSubRectangle) { + sourceSubRectangleString = ', sourceSubRectangle=' + sourceSubRectangle; + } + debug(''); + debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + + ' with flipY=' + flipY + ' and premultiplyAlpha=' + premultiplyAlpha + + ', bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') + + sourceSubRectangleString); + + var loc; + var skipCorner = false; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + loc = gl.getUniformLocation(program, "face"); + switch (gl[pixelFormat]) { + case gl.RED_INTEGER: + case gl.RG_INTEGER: + case gl.RGB_INTEGER: + case gl.RGBA_INTEGER: + // https://github.com/KhronosGroup/WebGL/issues/1819 + skipCorner = true; + break; + } + } + + if (skipCorner && expected.length == 1 && (flipY ^ sourceSubRectangle[1] == 0)) { + debug("Test skipped, see WebGL#1819"); + return; + } + + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Enable writes to the RGBA channels + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); + var targets = [gl.TEXTURE_2D]; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; + } + // Handle the source sub-rectangle if specified (WebGL 2.0 only) + if (sourceSubRectangle) { + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); + } + // Upload the image into the texture + for (var tt = 0; tt < targets.length; ++tt) { + if (sourceSubRectangle) { + if (useTexSubImage2D) { + // Initialize the texture to black first + gl.texImage2D(targets[tt], 0, gl[internalFormat], + sourceSubRectangle[2], sourceSubRectangle[3], 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, + sourceSubRectangle[2], sourceSubRectangle[3], + gl[pixelFormat], gl[pixelType], imageData); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], + sourceSubRectangle[2], sourceSubRectangle[3], 0, + gl[pixelFormat], gl[pixelType], imageData); + } + } else { + if (useTexSubImage2D) { + // Initialize the texture to black first + gl.texImage2D(targets[tt], 0, gl[internalFormat], imageData.width, imageData.height, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], imageData); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], imageData); + } + } + } + + if (sourceSubRectangle) { + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + } + + var width = gl.canvas.width; + var halfWidth = Math.floor(width / 2); + var height = gl.canvas.height; + var halfHeight = Math.floor(height / 2); + + var top = 0; + var bottom = height - halfHeight; + var left = 0; + var right = width - halfWidth; + + var tl, tr, bl, br; + if (expected.length == 1) { + tl = tr = bl = br = expected[0]; + } else { + tl = expected[0]; + tr = expected[1]; + bl = expected[2]; + br = expected[3]; + } + + for (var tt = 0; tt < targets.length; ++tt) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + gl.uniform1i(loc, targets[tt]); + } + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + + // Check the top pixel and bottom pixel and make sure they have + // the right color. + wtu.checkCanvasRect(gl, left, top, halfWidth, halfHeight, tl, "shouldBe " + tl); + if (!skipCorner) { + wtu.checkCanvasRect(gl, right, top, halfWidth, halfHeight, tr, "shouldBe " + tr); + } + wtu.checkCanvasRect(gl, left, bottom, halfWidth, halfHeight, bl, "shouldBe " + bl); + if (!skipCorner) { + wtu.checkCanvasRect(gl, right, bottom, halfWidth, halfHeight, br, "shouldBe " + br); + } + } + } + + function runTest() + { + var program = tiu.setupTexturedQuad(gl, internalFormat); + runTestOnBindingTarget(gl.TEXTURE_2D, program); + program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); + runTestOnBindingTarget(gl.TEXTURE_CUBE_MAP, program); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + } + + function runTestOnBindingTarget(bindingTarget, program) { + var k = blackColor; + var r = redColor; + var g = greenColor; + var cases = [ + { expected: [r, r, g, g], flipY: false, premultiplyAlpha: false, sub: false }, + { expected: [r, r, g, g], flipY: false, premultiplyAlpha: false, sub: true }, + { expected: [r, k, g, k], flipY: false, premultiplyAlpha: true, sub: false }, + { expected: [r, k, g, k], flipY: false, premultiplyAlpha: true, sub: true }, + { expected: [g, g, r, r], flipY: true, premultiplyAlpha: false, sub: false }, + { expected: [g, g, r, r], flipY: true, premultiplyAlpha: false, sub: true }, + { expected: [g, k, r, k], flipY: true, premultiplyAlpha: true, sub: false }, + { expected: [g, k, r, k], flipY: true, premultiplyAlpha: true, sub: true }, + ]; + + if (wtu.getDefault3DContextVersion() > 1) { + var morecases = []; + // Make 2 copies of the original case: top left and bottom right 1x1 rectangles + for (var i = 0; i < cases.length; i++) { + for (var subX = 0; subX <= 1; subX++) { + var subY = subX == 0 ? 1 : 0; + // shallow-copy cases[i] into newcase + var newcase = Object.assign({}, cases[i]); + newcase.expected = [cases[i].expected[subY * 2 + subX]]; + newcase.sourceSubRectangle = [subX, subY, 1, 1]; + morecases.push(newcase); + } + } + cases = cases.concat(morecases); + } + + for (var i in cases) { + runOneIteration(cases[i].sub, cases[i].flipY, cases[i].premultiplyAlpha, + cases[i].sourceSubRectangle, cases[i].expected, + bindingTarget, program); + } + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image.js new file mode 100644 index 000000000..51de6018d --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-image.js @@ -0,0 +1,263 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var imgCanvas; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking image elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + break; + + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + wtu.loadTexture(gl, resourcePath + "red-green.png", runTest); + } + + function runOneIteration(image, useTexSubImage2D, flipY, topColor, bottomColor, + sourceSubRectangle, bindingTarget, program) + { + sourceSubRectangleString = ''; + if (sourceSubRectangle) { + sourceSubRectangleString = ' sourceSubRectangle=' + sourceSubRectangle; + } + debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + + ' with ' + image.width + 'x' + image.height + ' flipY=' + flipY + ' bindingTarget=' + + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') + + sourceSubRectangleString); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Disable any writes to the alpha channel + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);'); + var targets = [gl.TEXTURE_2D]; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; + } + // Handle the source sub-rectangle if specified (WebGL 2.0 only) + if (sourceSubRectangle) { + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); + } + // Upload the image into the texture + for (var tt = 0; tt < targets.length; ++tt) { + if (sourceSubRectangle) { + if (useTexSubImage2D) { + // Initialize the texture to black first + gl.texImage2D(targets[tt], 0, gl[internalFormat], + sourceSubRectangle[2], sourceSubRectangle[3], 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, + sourceSubRectangle[2], sourceSubRectangle[3], + gl[pixelFormat], gl[pixelType], image); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], + sourceSubRectangle[2], sourceSubRectangle[3], 0, + gl[pixelFormat], gl[pixelType], image); + } + } else { + if (useTexSubImage2D) { + // Initialize the texture to black first + gl.texImage2D(targets[tt], 0, gl[internalFormat], image.width, image.height, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], image); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], image); + } + } + } + + if (sourceSubRectangle) { + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + } + + var loc; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + loc = gl.getUniformLocation(program, "face"); + } + + for (var tt = 0; tt < targets.length; ++tt) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + gl.uniform1i(loc, targets[tt]); + } + + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + // Check a few pixels near the top and bottom and make sure they have + // the right color. + debug("Checking lower left corner"); + wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor, + "shouldBe " + bottomColor); + debug("Checking upper left corner"); + wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor, + "shouldBe " + topColor); + } + } + + function runTestOnImage(image) { + var cases = [ + { sub: false, flipY: true, topColor: redColor, bottomColor: greenColor }, + { sub: false, flipY: false, topColor: greenColor, bottomColor: redColor }, + { sub: true, flipY: true, topColor: redColor, bottomColor: greenColor }, + { sub: true, flipY: false, topColor: greenColor, bottomColor: redColor }, + ]; + + + if (wtu.getDefault3DContextVersion() > 1) { + cases = cases.concat([ + { sub: false, flipY: false, topColor: redColor, bottomColor: redColor, + sourceSubRectangle: [0, 0, 1, 1] }, + { sub: false, flipY: true, topColor: greenColor, bottomColor: greenColor, + sourceSubRectangle: [0, 0, 1, 1] }, + { sub: false, flipY: false, topColor: greenColor, bottomColor: greenColor, + sourceSubRectangle: [0, 1, 1, 1] }, + { sub: false, flipY: true, topColor: redColor, bottomColor: redColor, + sourceSubRectangle: [0, 1, 1, 1] }, + { sub: true, flipY: false, topColor: redColor, bottomColor: redColor, + sourceSubRectangle: [0, 0, 1, 1] }, + { sub: true, flipY: true, topColor: greenColor, bottomColor: greenColor, + sourceSubRectangle: [0, 0, 1, 1] }, + { sub: true, flipY: false, topColor: greenColor, bottomColor: greenColor, + sourceSubRectangle: [0, 1, 1, 1] }, + { sub: true, flipY: true, topColor: redColor, bottomColor: redColor, + sourceSubRectangle: [0, 1, 1, 1] }, + ]); + } + + var program = tiu.setupTexturedQuad(gl, internalFormat); + for (var i in cases) { + runOneIteration(image, cases[i].sub, cases[i].flipY, + cases[i].topColor, cases[i].bottomColor, + cases[i].sourceSubRectangle, + gl.TEXTURE_2D, program); + } + // cube map texture must be square. + if (image.width != image.height) + return; + // Skip sub-rectangle tests for cube map textures for the moment. + program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); + for (var i in cases) { + if (!cases[i].sourceSubRectangle) { + runOneIteration(image, cases[i].sub, cases[i].flipY, + cases[i].topColor, cases[i].bottomColor, + undefined, + gl.TEXTURE_CUBE_MAP, program); + } + } + } + + function runTest(image) + { + runTestOnImage(image); + + imgCanvas = document.createElement("canvas"); + imgCanvas.width = 2; + imgCanvas.height = 2; + var imgCtx = imgCanvas.getContext("2d"); + var imgData = imgCtx.createImageData(2, 2); + imgData.data[0] = redColor[0]; + imgData.data[1] = redColor[1]; + imgData.data[2] = redColor[2]; + imgData.data[3] = 255; + imgData.data[4] = redColor[0]; + imgData.data[5] = redColor[1]; + imgData.data[6] = redColor[2]; + imgData.data[7] = 255; + imgData.data[8] = greenColor[0]; + imgData.data[9] = greenColor[1]; + imgData.data[10] = greenColor[2]; + imgData.data[11] = 255; + imgData.data[12] = greenColor[0]; + imgData.data[13] = greenColor[1]; + imgData.data[14] = greenColor[2]; + imgData.data[15] = 255; + imgCtx.putImageData(imgData, 0, 0); + + // apparently Image is different than <img>. + var newImage = new Image(); + newImage.onload = function() { + runTest2(newImage); + }; + newImage.onerror = function() { + testFailed("Creating image from canvas failed. Image src: " + this.src); + finishTest(); + }; + newImage.src = imgCanvas.toDataURL(); + } + + function runTest2(image) { + runTestOnImage(image); + + wtu.makeImageFromCanvas(imgCanvas, function() { + runTest3(this); + }); + } + + function runTest3(image) { + runTestOnImage(image); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-svg-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-svg-image.js new file mode 100644 index 000000000..be5a845b1 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-svg-image.js @@ -0,0 +1,148 @@ +/* +** Copyright (c) 2013 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var imgCanvas; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking SVG image elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + break; + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + wtu.loadTexture(gl, resourcePath + "red-green.svg", runTest); + } + + function runOneIteration(image, useTexSubImage2D, flipY, topColor, bottomColor, bindingTarget, program) + { + debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + + ' with flipY=' + flipY + ' bindingTarget=' + + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP')); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Disable any writes to the alpha channel + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);'); + var targets = [gl.TEXTURE_2D]; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; + } + // Upload the image into the texture + for (var tt = 0; tt < targets.length; ++tt) { + if (useTexSubImage2D) { + // Initialize the texture to black first + gl.texImage2D(targets[tt], 0, gl[internalFormat], image.width, image.height, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], image); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], image); + } + } + + var loc; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + loc = gl.getUniformLocation(program, "face"); + } + + for (var tt = 0; tt < targets.length; ++tt) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + gl.uniform1i(loc, targets[tt]); + } + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + // Check a few pixels near the top and bottom and make sure they have + // the right color. + debug("Checking lower left corner"); + wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor, + "shouldBe " + bottomColor); + debug("Checking upper left corner"); + wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor, + "shouldBe " + topColor); + } + } + + function runTest(image) + { + var program = tiu.setupTexturedQuad(gl, internalFormat); + runTestOnBindingTarget(image, gl.TEXTURE_2D, program); + program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); + runTestOnBindingTarget(image, gl.TEXTURE_CUBE_MAP, program); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + } + + function runTestOnBindingTarget(image, bindingTarget, program) { + var cases = [ + { sub: false, flipY: true, topColor: redColor, bottomColor: greenColor }, + { sub: false, flipY: false, topColor: greenColor, bottomColor: redColor }, + { sub: true, flipY: true, topColor: redColor, bottomColor: greenColor }, + { sub: true, flipY: false, topColor: greenColor, bottomColor: redColor }, + ]; + for (var i in cases) { + runOneIteration(image, cases[i].sub, cases[i].flipY, + cases[i].topColor, cases[i].bottomColor, + bindingTarget, program); + } + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-video.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-video.js new file mode 100644 index 000000000..2d0103059 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-video.js @@ -0,0 +1,299 @@ +/* +** 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. +*/ + +// This block needs to be outside the onload handler in order for this +// test to run reliably in WebKit's test harness (at least the +// Chromium port). https://bugs.webkit.org/show_bug.cgi?id=87448 +initTestingHarness(); + +var old = debug; +var debug = function(msg) { + bufferedLogToConsole(msg); + old(msg); +}; + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + + // Test each format separately because many browsers implement each + // differently. Some might be GPU accelerated, some might not. Etc... + var videos = [ + { src: resourcePath + "red-green.mp4" , type: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', }, + { src: resourcePath + "red-green.webmvp8.webm", type: 'video/webm; codecs="vp8, vorbis"', }, + { src: resourcePath + "red-green.webmvp9.webm", type: 'video/webm; codecs="vp9"', }, + { src: resourcePath + "red-green.theora.ogv", type: 'video/ogg; codecs="theora, vorbis"', }, + ]; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking video elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + break; + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + runTest(); + } + + function runOneIteration(videoElement, useTexSubImage2D, flipY, topColor, bottomColor, sourceSubRectangle, program, bindingTarget) + { + sourceSubRectangleString = ''; + if (sourceSubRectangle) { + sourceSubRectangleString = ' sourceSubRectangle=' + sourceSubRectangle; + } + debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + + ' with flipY=' + flipY + ' bindingTarget=' + + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') + + sourceSubRectangleString); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Disable any writes to the alpha channel + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + var targets = [gl.TEXTURE_2D]; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; + } + // Handle the source sub-rectangle if specified (WebGL 2.0 only) + if (sourceSubRectangle) { + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); + } + // Upload the videoElement into the texture + for (var tt = 0; tt < targets.length; ++tt) { + if (sourceSubRectangle) { + // Initialize the texture to black first + if (useTexSubImage2D) { + // Skip sub-rectangle tests for cube map textures for the moment. + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + continue; + } + gl.texImage2D(targets[tt], 0, gl[internalFormat], + sourceSubRectangle[2], sourceSubRectangle[3], 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, + sourceSubRectangle[2], sourceSubRectangle[3], + gl[pixelFormat], gl[pixelType], videoElement); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], + sourceSubRectangle[2], sourceSubRectangle[3], 0, + gl[pixelFormat], gl[pixelType], videoElement); + } + } else { + // Initialize the texture to black first + if (useTexSubImage2D) { + var width = videoElement.videoWidth; + var height = videoElement.videoHeight; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + // cube map texture must be square. + width = Math.max(width, height); + height = width; + } + gl.texImage2D(targets[tt], 0, gl[internalFormat], + width, height, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], videoElement); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], videoElement); + } + } + } + + if (sourceSubRectangle) { + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + } + + var c = document.createElement("canvas"); + c.width = 16; + c.height = 16; + c.style.border = "1px solid black"; + var ctx = c.getContext("2d"); + ctx.drawImage(videoElement, 0, 0, 16, 16); + document.body.appendChild(c); + + var loc; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + loc = gl.getUniformLocation(program, "face"); + } + + for (var tt = 0; tt < targets.length; ++tt) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + gl.uniform1i(loc, targets[tt]); + } + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + // Check a few pixels near the top and bottom and make sure they have + // the right color. + var tolerance = 5; + debug("Checking lower left corner"); + wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor, + "shouldBe " + bottomColor, tolerance); + debug("Checking upper left corner"); + wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor, + "shouldBe " + topColor, tolerance); + } + } + + function runTest(videoElement) + { + var cases = [ + { sub: false, flipY: true, topColor: redColor, bottomColor: greenColor }, + { sub: false, flipY: false, topColor: greenColor, bottomColor: redColor }, + { sub: true, flipY: true, topColor: redColor, bottomColor: greenColor }, + { sub: true, flipY: false, topColor: greenColor, bottomColor: redColor }, + ]; + + if (wtu.getDefault3DContextVersion() > 1) { + cases = cases.concat([ + { sub: false, flipY: false, topColor: redColor, bottomColor: redColor, + sourceSubRectangle: [20, 16, 40, 32] }, + { sub: false, flipY: true, topColor: greenColor, bottomColor: greenColor, + sourceSubRectangle: [20, 16, 40, 32] }, + { sub: false, flipY: false, topColor: greenColor, bottomColor: greenColor, + sourceSubRectangle: [20, 80, 40, 32] }, + { sub: false, flipY: true, topColor: redColor, bottomColor: redColor, + sourceSubRectangle: [20, 80, 40, 32] }, + { sub: true, flipY: false, topColor: redColor, bottomColor: redColor, + sourceSubRectangle: [20, 16, 40, 32] }, + { sub: true, flipY: true, topColor: greenColor, bottomColor: greenColor, + sourceSubRectangle: [20, 16, 40, 32] }, + { sub: true, flipY: false, topColor: greenColor, bottomColor: greenColor, + sourceSubRectangle: [20, 80, 40, 32] }, + { sub: true, flipY: true, topColor: redColor, bottomColor: redColor, + sourceSubRectangle: [20, 80, 40, 32] }, + ]); + } + + function runTexImageTest(bindingTarget) { + var program; + if (bindingTarget == gl.TEXTURE_2D) { + program = tiu.setupTexturedQuad(gl, internalFormat); + } else { + program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); + } + + return new Promise(function(resolve, reject) { + var videoNdx = 0; + var video; + function runNextVideo() { + if (video) { + video.pause(); + } + + if (videoNdx == videos.length) { + resolve("SUCCESS"); + return; + } + + var info = videos[videoNdx++]; + debug(""); + debug("testing: " + info.type); + video = document.createElement("video"); + var canPlay = true; + if (!video.canPlayType) { + testFailed("video.canPlayType required method missing"); + runNextVideo(); + return; + } + + if(!video.canPlayType(info.type).replace(/no/, '')) { + debug(info.type + " unsupported"); + runNextVideo(); + return; + }; + + document.body.appendChild(video); + video.type = info.type; + video.src = info.src; + wtu.startPlayingAndWaitForVideo(video, runTest); + } + function runTest() { + for (var i in cases) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + // Cube map texture must be square but video is not square. + if (!cases[i].sub) { + break; + } + // Skip sub-rectangle tests for cube map textures for the moment. + if (cases[i].sourceSubRectangle) { + break; + } + } + runOneIteration(video, cases[i].sub, cases[i].flipY, + cases[i].topColor, cases[i].bottomColor, + cases[i].sourceSubRectangle, + program, bindingTarget); + } + runNextVideo(); + } + runNextVideo(); + }); + } + + runTexImageTest(gl.TEXTURE_2D).then(function(val) { + runTexImageTest(gl.TEXTURE_CUBE_MAP).then(function(val) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + }); + }); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js new file mode 100644 index 000000000..534965ba3 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-2d-with-webgl-canvas.js @@ -0,0 +1,249 @@ +/* +** Copyright (c) 2014 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + + function init() + { + description('Verify texImage2D and texSubImage2D code paths taking webgl canvas elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + break; + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + runTest(); + } + + function setCanvasToRedGreen(ctx) { + var width = ctx.canvas.width; + var height = ctx.canvas.height; + var halfHeight = Math.floor(height / 2); + + ctx.viewport(0, 0, width, height); + + ctx.enable(ctx.SCISSOR_TEST); + ctx.scissor(0, 0, width, halfHeight); + ctx.clearColor(1.0, 0, 0, 1.0); + ctx.clear(ctx.COLOR_BUFFER_BIT); + ctx.scissor(0, halfHeight, width, height - halfHeight); + ctx.clearColor(0.0, 1.0, 0, 1.0); + ctx.clear(ctx.COLOR_BUFFER_BIT); + ctx.disable(ctx.SCISSOR_TEST); + } + + function setCanvasTo257x257(ctx, bindingTarget) { + ctx.canvas.width = 257; + ctx.canvas.height = 257; + setCanvasToRedGreen(ctx); + } + + function setCanvasToMin(ctx, bindingTarget) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + // cube map texture must be square. + ctx.canvas.width = 2; + } else { + ctx.canvas.width = 1; + } + ctx.canvas.height = 2; + setCanvasToRedGreen(ctx); + } + + function runOneIteration(canvas, useTexSubImage2D, flipY, program, bindingTarget, opt_texture) + { + debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + ' with flipY=' + + flipY + ' bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') + + ' canvas size: ' + canvas.width + 'x' + canvas.height + ' with red-green'); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + if (!opt_texture) { + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } else { + var texture = opt_texture; + } + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);'); + var targets = [gl.TEXTURE_2D]; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; + } + // Upload the image into the texture + for (var tt = 0; tt < targets.length; ++tt) { + // Initialize the texture to black first + if (useTexSubImage2D) { + gl.texImage2D(targets[tt], 0, gl[internalFormat], canvas.width, canvas.height, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], canvas); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], canvas); + } + } + + var width = gl.canvas.width; + var height = gl.canvas.height; + var halfWidth = Math.floor(width / 2); + var halfHeight = Math.floor(height / 2); + var top = flipY ? (height - halfHeight) : 0; + var bottom = flipY ? 0 : (height - halfHeight); + + var loc; + var skipCorner = false; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + loc = gl.getUniformLocation(program, "face"); + switch (gl[pixelFormat]) { + case gl.RED_INTEGER: + case gl.RG_INTEGER: + case gl.RGB_INTEGER: + case gl.RGBA_INTEGER: + // https://github.com/KhronosGroup/WebGL/issues/1819 + skipCorner = true; + break; + } + } + + for (var tt = 0; tt < targets.length; ++tt) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + gl.uniform1i(loc, targets[tt]); + } + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]); + + // Check the top and bottom halves and make sure they have the right color. + debug("Checking " + (flipY ? "top" : "bottom")); + wtu.checkCanvasRect(gl, 0, bottom, (skipCorner && !flipY) ? halfWidth : width, halfHeight, redColor, + "shouldBe " + redColor); + debug("Checking " + (flipY ? "bottom" : "top")); + wtu.checkCanvasRect(gl, 0, top, (skipCorner && flipY) ? halfWidth : width, halfHeight, greenColor, + "shouldBe " + greenColor); + } + + if (false) { + var ma = wtu.makeImageFromCanvas(canvas); + document.getElementById("console").appendChild(ma); + + var m = wtu.makeImageFromCanvas(gl.canvas); + document.getElementById("console").appendChild(m); + document.getElementById("console").appendChild(document.createElement("hr")); + } + + return texture; + } + + function runTest() + { + var ctx = wtu.create3DContext(); + var canvas = ctx.canvas; + + var cases = [ + { sub: false, flipY: true, init: setCanvasToMin }, + { sub: false, flipY: false }, + { sub: true, flipY: true }, + { sub: true, flipY: false }, + { sub: false, flipY: true, init: setCanvasTo257x257 }, + { sub: false, flipY: false }, + { sub: true, flipY: true }, + { sub: true, flipY: false }, + ]; + + function runTexImageTest(bindingTarget) { + var program; + if (bindingTarget == gl.TEXTURE_2D) { + program = tiu.setupTexturedQuad(gl, internalFormat); + } else { + program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); + } + + return new Promise(function(resolve, reject) { + var count = 4; + var caseNdx = 0; + var texture = undefined; + function runNextTest() { + var c = cases[caseNdx]; + if (c.init) { + c.init(ctx, bindingTarget); + } + texture = runOneIteration(canvas, c.sub, c.flipY, program, bindingTarget, texture); + // for the first 2 iterations always make a new texture. + if (count > 2) { + texture = undefined; + } + ++caseNdx; + if (caseNdx == cases.length) { + caseNdx = 0; + --count; + if (!count) { + resolve("SUCCESS"); + return; + } + } + wtu.waitForComposite(runNextTest); + } + runNextTest(); + }); + } + + runTexImageTest(gl.TEXTURE_2D).then(function(val) { + runTexImageTest(gl.TEXTURE_CUBE_MAP).then(function(val) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + }); + }); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js new file mode 100644 index 000000000..be7e2cea4 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas-sub-rectangle.js @@ -0,0 +1,304 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var realRedColor = [255, 0, 0]; + var realGreenColor = [0, 255, 0]; + var realBlueColor = [0, 0, 255]; + var realCyanColor = [0, 255, 255]; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + var blueColor = [0, 0, 255]; + var cyanColor = [0, 255, 255]; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking a sub-rectangle of a canvas (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + blueColor = [0, 0, 0]; + cyanColor = [0, 0, 0]; + break; + + case gl.RG: + case gl.RG_INTEGER: + blueColor = [0, 0, 0]; + cyanColor = [0, 255, 0]; + break; + + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + var canvas2d = document.createElement('canvas'); + runTest(canvas2d, setupSourceCanvas2D, '2D-rendered canvas'); + + var canvasWebGL = document.createElement('canvas'); + runTest(canvasWebGL, setupSourceCanvasWebGL, 'WebGL-rendered canvas'); + + finishTest(); + } + + function uploadCanvasToTexture(canvas, useTexSubImage3D, flipY, bindingTarget, + depth, sourceSubRectangle, unpackImageHeight) + { + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Disable any writes to the alpha channel + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); + var uploadWidth = canvas.width; + var uploadHeight = canvas.height; + if (sourceSubRectangle) { + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); + uploadWidth = sourceSubRectangle[2]; + uploadHeight = sourceSubRectangle[3]; + } + if (unpackImageHeight) { + gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight); + } + // Upload the image into the texture + if (useTexSubImage3D) { + // Initialize the texture to black first + gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, uploadWidth, uploadHeight, depth, + gl[pixelFormat], gl[pixelType], canvas); + } else { + gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0, + gl[pixelFormat], gl[pixelType], canvas); + } + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from texture upload"); + } + + function fillStyle2D(ctx, color) { + ctx.fillStyle = 'rgb(' + color[0] + ', ' + color[1] + ', ' + color[2] + ')'; + } + + function setupSourceCanvas2D(canvas) { + var width = canvas.width; + var height = canvas.height; + var halfWidth = Math.floor(width / 2); + var halfHeight = Math.floor(height / 2); + + var ctx = canvas.getContext('2d'); + // Always use the same pattern for this test: four quadrants: + // red green + // blue cyan + // Handle odd-sized canvases + fillStyle2D(ctx, realRedColor); + ctx.fillRect(0, 0, halfWidth, halfHeight); + fillStyle2D(ctx, realGreenColor); + ctx.fillRect(halfWidth, 0, width - halfWidth, halfHeight); + fillStyle2D(ctx, realBlueColor); + ctx.fillRect(0, halfHeight, halfWidth, height - halfHeight); + fillStyle2D(ctx, realCyanColor); + ctx.fillRect(halfWidth, halfHeight, width - halfWidth, height - halfHeight); + } + + function clearColorWebGL(ctx, color) { + ctx.clearColor(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0, 1.0); + ctx.clear(ctx.COLOR_BUFFER_BIT); + } + + function setupSourceCanvasWebGL(canvas) { + var width = canvas.width; + var height = canvas.height; + var halfWidth = Math.floor(width / 2); + var halfHeight = Math.floor(height / 2); + + var ctx = canvas.getContext('webgl'); + // Always use the same pattern for this test: four quadrants: + // red green + // blue cyan + // Handle odd-sized canvases + + ctx.viewport(0, 0, width, height); + ctx.enable(ctx.SCISSOR_TEST); + // OpenGL origin is lower-left + ctx.scissor(0, 0, halfWidth, halfHeight); + clearColorWebGL(ctx, realBlueColor); + ctx.scissor(halfWidth, 0, width - halfWidth, halfHeight); + clearColorWebGL(ctx, realCyanColor); + ctx.scissor(0, halfHeight, halfWidth, height - halfHeight); + clearColorWebGL(ctx, realRedColor); + ctx.scissor(halfWidth, halfHeight, width - halfWidth, height - halfHeight); + clearColorWebGL(ctx, realGreenColor); + } + + function runOneIteration(canvas, useTexSubImage3D, flipY, bindingTarget, + depth, sourceSubRectangle, unpackImageHeight, + rTextureCoord, expectedColor, program, + canvasSize, canvasSetupFunction, sourceDescription) + { + debug(''); + debug('Testing ' + sourceDescription + ' with ' + + (useTexSubImage3D ? 'texSubImage3D' : 'texImage3D') + + ', flipY=' + flipY + ', bindingTarget=' + + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') + + ', sourceSubRectangle=' + sourceSubRectangle + + ', depth=' + depth + + (unpackImageHeight ? ', unpackImageHeight=' + unpackImageHeight : '') + + ', rTextureCoord=' + rTextureCoord); + + // Initialize the contents of the source canvas. + var width = canvasSize[0]; + var height = canvasSize[1]; + var halfWidth = Math.floor(width / 2); + var halfHeight = Math.floor(height / 2); + canvas.width = width; + canvas.height = height; + canvasSetupFunction(canvas); + + uploadCanvasToTexture(canvas, useTexSubImage3D, flipY, bindingTarget, + depth, sourceSubRectangle, unpackImageHeight); + var rCoordLocation = gl.getUniformLocation(program, 'uRCoord'); + if (!rCoordLocation) { + testFailed('Shader incorrectly set up; couldn\'t find uRCoord uniform'); + return; + } + gl.uniform1f(rCoordLocation, rTextureCoord); + + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + // Check the rendered canvas + wtu.checkCanvasRect(gl, 0, 0, canvasSize[0], canvasSize[1], expectedColor, "shouldBe " + expectedColor); + } + + function runTest(canvas, canvasSetupFunction, sourceDescription) + { + var cases = [ + // Small canvas cases. Expected that these won't be + // GPU-accelerated in most browsers' implementations. + + // No UNPACK_IMAGE_HEIGHT specified. + { expected: redColor, flipY: false, size: [4, 4], subRect: [0, 0, 2, 2], depth: 2, rTextureCoord: 0.0 }, + { expected: blueColor, flipY: false, size: [4, 4], subRect: [0, 0, 2, 2], depth: 2, rTextureCoord: 1.0 }, + { expected: blueColor, flipY: true, size: [4, 4], subRect: [0, 0, 2, 2], depth: 2, rTextureCoord: 0.0 }, + { expected: redColor, flipY: true, size: [4, 4], subRect: [0, 0, 2, 2], depth: 2, rTextureCoord: 1.0 }, + { expected: greenColor, flipY: false, size: [4, 4], subRect: [2, 0, 2, 2], depth: 2, rTextureCoord: 0.0 }, + { expected: cyanColor, flipY: false, size: [4, 4], subRect: [2, 0, 2, 2], depth: 2, rTextureCoord: 1.0 }, + { expected: cyanColor, flipY: true, size: [4, 4], subRect: [2, 0, 2, 2], depth: 2, rTextureCoord: 0.0 }, + { expected: greenColor, flipY: true, size: [4, 4], subRect: [2, 0, 2, 2], depth: 2, rTextureCoord: 1.0 }, + + // Use UNPACK_IMAGE_HEIGHT to skip some pixels. + { expected: redColor, flipY: false, size: [4, 4], subRect: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0 }, + { expected: blueColor, flipY: false, size: [4, 4], subRect: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0 }, + { expected: blueColor, flipY: true, size: [4, 4], subRect: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0 }, + { expected: redColor, flipY: true, size: [4, 4], subRect: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0 }, + { expected: greenColor, flipY: false, size: [4, 4], subRect: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0 }, + { expected: cyanColor, flipY: false, size: [4, 4], subRect: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0 }, + { expected: cyanColor, flipY: true, size: [4, 4], subRect: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0 }, + { expected: greenColor, flipY: true, size: [4, 4], subRect: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0 }, + + // Larger canvas cases. Expected that these will be + // GPU-accelerated in most browsers' implementations. + // Changes will be gladly accepted to trigger more + // browsers' heuristics to accelerate these canvases. + + // No UNPACK_IMAGE_HEIGHT specified. + { expected: redColor, flipY: false, size: [384, 384], subRect: [0, 0, 192, 192], depth: 2, rTextureCoord: 0.0 }, + { expected: blueColor, flipY: false, size: [384, 384], subRect: [0, 0, 192, 192], depth: 2, rTextureCoord: 1.0 }, + { expected: blueColor, flipY: true, size: [384, 384], subRect: [0, 0, 192, 192], depth: 2, rTextureCoord: 0.0 }, + { expected: redColor, flipY: true, size: [384, 384], subRect: [0, 0, 192, 192], depth: 2, rTextureCoord: 1.0 }, + { expected: greenColor, flipY: false, size: [384, 384], subRect: [192, 0, 192, 192], depth: 2, rTextureCoord: 0.0 }, + { expected: cyanColor, flipY: false, size: [384, 384], subRect: [192, 0, 192, 192], depth: 2, rTextureCoord: 1.0 }, + { expected: cyanColor, flipY: true, size: [384, 384], subRect: [192, 0, 192, 192], depth: 2, rTextureCoord: 0.0 }, + { expected: greenColor, flipY: true, size: [384, 384], subRect: [192, 0, 192, 192], depth: 2, rTextureCoord: 1.0 }, + + // Use UNPACK_IMAGE_HEIGHT to skip some pixels. + { expected: redColor, flipY: false, size: [384, 384], subRect: [0, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 0.0 }, + { expected: blueColor, flipY: false, size: [384, 384], subRect: [0, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 1.0 }, + { expected: blueColor, flipY: true, size: [384, 384], subRect: [0, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 0.0 }, + { expected: redColor, flipY: true, size: [384, 384], subRect: [0, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 1.0 }, + { expected: greenColor, flipY: false, size: [384, 384], subRect: [192, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 0.0 }, + { expected: cyanColor, flipY: false, size: [384, 384], subRect: [192, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 1.0 }, + { expected: cyanColor, flipY: true, size: [384, 384], subRect: [192, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 0.0 }, + { expected: greenColor, flipY: true, size: [384, 384], subRect: [192, 0, 96, 96], depth: 2, unpackImageHeight: 192, rTextureCoord: 1.0 }, + ]; + + var program = tiu.setupTexturedQuadWith3D(gl, internalFormat); + for (var i in cases) { + runOneIteration(canvas, false, cases[i].flipY, gl.TEXTURE_3D, + cases[i].depth, cases[i].subRect, + cases[i].unpackImageHeight, cases[i].rTextureCoord, + cases[i].expected, + program, cases[i].size, canvasSetupFunction, sourceDescription); + runOneIteration(canvas, true, cases[i].flipY, gl.TEXTURE_3D, + cases[i].depth, cases[i].subRect, + cases[i].unpackImageHeight, cases[i].rTextureCoord, + cases[i].expected, + program, cases[i].size, canvasSetupFunction, sourceDescription); + } + + program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); + for (var i in cases) { + runOneIteration(canvas, false, cases[i].flipY, gl.TEXTURE_2D_ARRAY, + cases[i].depth, cases[i].subRect, + cases[i].unpackImageHeight, cases[i].rTextureCoord, + cases[i].expected, + program, cases[i].size, canvasSetupFunction, sourceDescription); + runOneIteration(canvas, true, cases[i].flipY, gl.TEXTURE_2D_ARRAY, + cases[i].depth, cases[i].subRect, + cases[i].unpackImageHeight, cases[i].rTextureCoord, + cases[i].expected, + program, cases[i].size, canvasSetupFunction, sourceDescription); + } + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas.js new file mode 100644 index 000000000..c577d0f44 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-canvas.js @@ -0,0 +1,233 @@ +/* +** Copyright (c) 2015 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var whiteColor = [255, 255, 255, 255]; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking canvas elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + whiteColor = [255, 0, 0, 255]; + greenColor = [0, 0, 0]; + break; + case gl.RG: + case gl.RG_INTEGER: + whiteColor = [255, 255, 0, 255]; + break; + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + var testCanvas = document.createElement('canvas'); + runTest(testCanvas); + //document.body.appendChild(testCanvas); + } + + function setCanvasToRedGreen(ctx) { + var width = ctx.canvas.width; + var height = ctx.canvas.height; + var halfHeight = Math.floor(height / 2); + ctx.fillStyle = "#ff0000"; + ctx.fillRect(0, 0, width, halfHeight); + ctx.fillStyle = "#00ff00"; + ctx.fillRect(0, halfHeight, width, height - halfHeight); + } + + function drawTextInCanvas(ctx, bindingTarget) { + var width = ctx.canvas.width; + var height = ctx.canvas.height; + ctx.fillStyle = "#ffffff"; + ctx.fillRect(0, 0, width, height); + ctx.font = '20pt Arial'; + ctx.fillStyle = 'black'; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillText("1234567890", width / 2, height / 4); + } + + function setCanvasTo257x257(ctx, bindingTarget) { + ctx.canvas.width = 257; + ctx.canvas.height = 257; + setCanvasToRedGreen(ctx); + } + + function setCanvasToMin(ctx, bindingTarget) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + // cube map texture must be square. + ctx.canvas.width = 2; + } else { + ctx.canvas.width = 1; + } + ctx.canvas.height = 2; + setCanvasToRedGreen(ctx); + } + + function runOneIteration(canvas, flipY, program, bindingTarget, opt_texture, opt_fontTest) + { + debug('Testing ' + ' with flipY=' + flipY + ' bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') + + ' canvas size: ' + canvas.width + 'x' + canvas.height + (opt_fontTest ? " with fonts" : " with red-green")); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + if (!opt_texture) { + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } else { + var texture = opt_texture; + } + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);'); + // Initialize the texture to black first + gl.texImage3D(bindingTarget, 0, gl[internalFormat], canvas.width, canvas.height, 1 /* depth */, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, canvas.width, canvas.height, 1 /* depth */, + gl[pixelFormat], gl[pixelType], canvas); + + var width = gl.canvas.width; + var height = gl.canvas.height; + var halfHeight = Math.floor(height / 2); + var top = flipY ? 0 : (height - halfHeight); + var bottom = flipY ? (height - halfHeight) : 0; + + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]); + + if (opt_fontTest) { + // check half is a solid color. + wtu.checkCanvasRect( + gl, 0, top, width, halfHeight, + whiteColor, + "should be white"); + // check other half is not a solid color. + wtu.checkCanvasRectColor( + gl, 0, bottom, width, halfHeight, + whiteColor, 0, + function() { + testFailed("font missing"); + }, + function() { + testPassed("font renderered"); + }, + debug); + } else { + // Check the top and bottom halves and make sure they have the right color. + debug("Checking " + (flipY ? "top" : "bottom")); + wtu.checkCanvasRect(gl, 0, bottom, width, halfHeight, redColor, + "shouldBe " + redColor); + debug("Checking " + (flipY ? "bottom" : "top")); + wtu.checkCanvasRect(gl, 0, top, width, halfHeight, greenColor, + "shouldBe " + greenColor); + } + + return texture; + } + + function runTest(canvas) + { + var ctx = canvas.getContext("2d"); + + var cases = [ + { flipY: true, font: false, init: setCanvasToMin }, + { flipY: false, font: false }, + { flipY: true, font: false, init: setCanvasTo257x257 }, + { flipY: false, font: false }, + { flipY: true, font: true, init: drawTextInCanvas }, + { flipY: false, font: true }, + ]; + + function runTexImageTest(bindingTarget) { + var program; + if (bindingTarget == gl.TEXTURE_3D) { + program = tiu.setupTexturedQuadWith3D(gl, internalFormat); + } else { // TEXTURE_2D_ARRAY + program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); + } + + return new Promise(function(resolve, reject) { + var count = 4; + var caseNdx = 0; + var texture = undefined; + function runNextTest() { + var c = cases[caseNdx]; + if (c.init) { + c.init(ctx, bindingTarget); + } + texture = runOneIteration(canvas, c.flipY, program, bindingTarget, texture, c.font); + // for the first 2 iterations always make a new texture. + if (count > 2) { + texture = undefined; + } + ++caseNdx; + if (caseNdx == cases.length) { + caseNdx = 0; + --count; + if (!count) { + resolve("SUCCESS"); + return; + } + } + wtu.waitForComposite(runNextTest); + } + runNextTest(); + }); + } + + runTexImageTest(gl.TEXTURE_3D).then(function(val) { + runTexImageTest(gl.TEXTURE_2D_ARRAY).then(function(val) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + }); + }); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js new file mode 100644 index 000000000..1dab09bfa --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-blob.js @@ -0,0 +1,63 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from a Blob (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + var xhr = new XMLHttpRequest(); + xhr.open("GET", resourcePath + "red-green-semi-transparent.png"); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + var blob = xhr.response; + runImageBitmapTest(blob, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true); + finishTest(); + } + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js new file mode 100644 index 000000000..fb7d5e6ed --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-canvas.js @@ -0,0 +1,89 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from an HTMLCanvasElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + var testCanvas = document.createElement('canvas'); + var ctx = testCanvas.getContext("2d"); + setCanvasToMin(ctx); + runImageBitmapTest(testCanvas, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true); + + setCanvasTo257x257(ctx); + runImageBitmapTest(testCanvas, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true); + finishTest(); + } + + function setCanvasToRedGreen(ctx) { + var width = ctx.canvas.width; + var halfWidth = Math.floor(width / 2); + var height = ctx.canvas.height; + var halfHeight = Math.floor(height / 2); + ctx.fillStyle = "rgba(255, 0, 0, 1)"; + ctx.fillRect(0, 0, halfWidth, halfHeight); + ctx.fillStyle = "rgba(255, 0, 0, 0.5)"; + ctx.fillRect(halfWidth, 0, halfWidth, halfHeight); + ctx.fillStyle = "rgba(0, 255, 0, 1)"; + ctx.fillRect(0, halfHeight, halfWidth, halfHeight); + ctx.fillStyle = "rgba(0, 255, 0, 0.5)"; + ctx.fillRect(halfWidth, halfHeight, halfWidth, halfHeight); + } + + function setCanvasToMin(ctx) { + ctx.canvas.width = 2; + ctx.canvas.height = 2; + setCanvasToRedGreen(ctx); + } + + function setCanvasTo257x257(ctx) { + ctx.canvas.width = 257; + ctx.canvas.height = 257; + setCanvasToRedGreen(ctx); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js new file mode 100644 index 000000000..ba715426f --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-bitmap.js @@ -0,0 +1,67 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from an ImageBitmap (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + gl.disable(gl.BLEND); + + var imageData = new ImageData(new Uint8ClampedArray( + [255, 0, 0, 255, + 255, 0, 0, 0, + 0, 255, 0, 255, + 0, 255, 0, 0]), + 2, 2); + + createImageBitmap(imageData, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(bitmap) { + // bitmap is in unpremultiplied form + runImageBitmapTest(bitmap, 0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true); + finishTest(); + }); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js new file mode 100644 index 000000000..71411657b --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image-data.js @@ -0,0 +1,64 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from ImageData (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + gl.disable(gl.BLEND); + + var imageData = new ImageData(new Uint8ClampedArray( + [255, 0, 0, 255, + 255, 0, 0, 0, + 0, 255, 0, 255, + 0, 255, 0, 0]), + 2, 2); + + runImageBitmapTest(imageData, 0, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true); + finishTest(); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js new file mode 100644 index 000000000..2574becd1 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-image.js @@ -0,0 +1,60 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from an HTMLImageElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + var image = new Image(); + image.onload = function() { + runImageBitmapTest(image, 0.5, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true); + finishTest(); + } + image.src = resourcePath + "red-green-semi-transparent.png"; + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js new file mode 100644 index 000000000..e385ff90a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-bitmap-from-video.js @@ -0,0 +1,61 @@ +/* +** 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking ImageBitmap created from an HTMLVideoElement (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + if(!window.createImageBitmap || !window.ImageBitmap) { + finishTest(); + return; + } + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + video = document.createElement("video"); + video.oncanplaythrough = function() { + runImageBitmapTest(video, 1, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, true); + finishTest(); + } + video.src = resourcePath + "red-green.theora.ogv"; + document.body.appendChild(video); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-data.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-data.js new file mode 100644 index 000000000..e1368275d --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image-data.js @@ -0,0 +1,276 @@ +/* +** Copyright (c) 2015 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var imageData = null; + var blackColor = [0, 0, 0]; + var originalPixels = (function() { + // (red|green|blue|cyan)(opaque|transparent) + var ro = [255, 0, 0, 255]; var rt = [255, 0, 0, 0]; + var go = [0, 255, 0, 255]; var gt = [0, 255, 0, 0]; + var bo = [0, 0, 255, 255]; var bt = [0, 0, 255, 0]; + var co = [0, 255, 255, 255]; var ct = [0, 255, 255, 0]; + return [ro, rt, go, gt, + ro, rt, go, gt, + bo, bt, co, ct, + bo, bt, co, ct]; + })(); + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking ImageData (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + gl.disable(gl.BLEND); + + var canvas2d = document.getElementById("texcanvas"); + var context2d = canvas2d.getContext("2d"); + imageData = context2d.createImageData(4, 4); + var data = imageData.data; + for (var i = 0; i < originalPixels.length; i++) { + data.set(originalPixels[i], 4 * i); + } + + runTest(); + } + + function runOneIteration(useTexSubImage3D, flipY, premultiplyAlpha, bindingTarget, + depth, sourceSubRectangle, rTexCoord, program) + { + var expected = simulate(flipY, premultiplyAlpha, depth, sourceSubRectangle, rTexCoord); + var sourceSubRectangleString = ''; + if (sourceSubRectangle) { + sourceSubRectangleString = ', sourceSubRectangle=' + sourceSubRectangle; + sourceSubRectangleString += ', rTexCoord=' + rTexCoord; + } + debug(''); + debug('Testing ' + (useTexSubImage3D ? 'texSubImage3D' : 'texImage3D') + + ' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha + + ', bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') + + sourceSubRectangleString); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Enable writes to the RGBA channels + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); + gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); + var uploadWidth = imageData.width; + var uploadHeight = imageData.height; + if (sourceSubRectangle) { + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); + uploadWidth = sourceSubRectangle[2]; + uploadHeight = sourceSubRectangle[3]; + } + // Upload the image into the texture + if (useTexSubImage3D) { + // Initialize the texture to black first + gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, uploadWidth, uploadHeight, depth, + gl[pixelFormat], gl[pixelType], imageData); + } else { + gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0, + gl[pixelFormat], gl[pixelType], imageData); + } + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from texture upload"); + + var tl = expected[0][0]; + var tr = expected[0][1]; + var bl = expected[1][0]; + var br = expected[1][1]; + + var rCoordLocation = gl.getUniformLocation(program, 'uRCoord'); + if (!rCoordLocation) { + testFailed("Shader incorrectly set up; couldn't find uRCoord uniform"); + return; + } + gl.uniform1f(rCoordLocation, rTexCoord); + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + + var width = gl.canvas.width; + var halfWidth = Math.floor(width / 2); + var height = gl.canvas.height; + var halfHeight = Math.floor(height / 2); + + var top = 0; + var bottom = height - halfHeight; + var left = 0; + var right = width - halfWidth; + + debug("Checking pixel values"); + debug("Expecting: " + expected); + var expectedH = expected.length; + var expectedW = expected[0].length; + var texelH = Math.floor(gl.canvas.height / expectedH); + var texelW = Math.floor(gl.canvas.width / expectedW); + // For each entry of the expected[][] array, check the appropriate + // canvas rectangle for correctness. + for (var row = 0; row < expectedH; row++) { + var y = row * texelH; + for (var col = 0; col < expectedW; col++) { + var x = col * texelW; + var val = expected[row][col]; + wtu.checkCanvasRect(gl, x, y, texelW, texelH, val, "should be " + val); + } + } + } + + function runTest() + { + var program = tiu.setupTexturedQuadWith3D(gl, internalFormat); + runTestOnBindingTarget(gl.TEXTURE_3D, program); + program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); + runTestOnBindingTarget(gl.TEXTURE_2D_ARRAY, program); + + debug(""); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + } + + function simulate(flipY, premultiplyAlpha, depth, sourceSubRectangle, rTexCoord) { + var ro = [255, 0, 0]; var rt = premultiplyAlpha ? [0, 0, 0] : [255, 0, 0]; + var go = [0, 255, 0]; var gt = premultiplyAlpha ? [0, 0, 0] : [0, 255, 0]; + var bo = [0, 0, 255]; var bt = premultiplyAlpha ? [0, 0, 0] : [0, 0, 255]; + var co = [0, 255, 255]; var ct = premultiplyAlpha ? [0, 0, 0] : [0, 255, 255]; + var expected = [[ro, rt, go, gt], + [ro, rt, go, gt], + [bo, bt, co, ct], + [bo, bt, co, ct]]; + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + for (var row = 0; row < 4; row++) { + for (var col = 0; col < 4; col++) { + expected[row][col][1] = 0; // zero the green channel + } + } + // fall-through + case gl.RG: + case gl.RG_INTEGER: + for (var row = 0; row < 4; row++) { + for (var col = 0; col < 4; col++) { + expected[row][col][2] = 0; // zero the blue channel + } + } + break; + default: + break; + } + + if (flipY) { + expected.reverse(); + } + + if (sourceSubRectangle) { + let expected2 = []; + for (var row = 0; row < sourceSubRectangle[3]; row++) { + expected2[row] = []; + for (var col = 0; col < sourceSubRectangle[2]; col++) { + expected2[row][col] = + expected[sourceSubRectangle[1] + row + rTexCoord * sourceSubRectangle[3]][sourceSubRectangle[0] + col]; + } + } + expected = expected2; + } + + return expected; + } + + function runTestOnBindingTarget(bindingTarget, program) { + var rects = [ + undefined, + [0, 0, 2, 2], + [2, 0, 2, 2], + ]; + var dbg = false; // Set to true for debug output images + if (dbg) { + (function() { + debug(""); + debug("Original ImageData (transparent pixels appear black):"); + var cvs = document.createElement("canvas"); + cvs.width = 4; + cvs.height = 4; + cvs.style.width = "32px"; + cvs.style.height = "32px"; + cvs.style.imageRendering = "pixelated"; + cvs.style.background = "#000"; + var ctx = cvs.getContext("2d"); + ctx.putImageData(imageData, 0, 0); + var output = document.getElementById("console"); + output.appendChild(cvs); + })(); + } + for (const sub of [false, true]) { + for (const flipY of [false, true]) { + for (const premul of [false, true]) { + for (let irect = 0; irect < rects.length; irect++) { + var rect = rects[irect]; + let depth = rect ? 2 : 1; + for (let rTexCoord = 0; rTexCoord < depth; rTexCoord++) { + // TODO: add tests for UNPACK_IMAGE_HEIGHT. + runOneIteration(sub, flipY, premul, bindingTarget, + depth, rect, rTexCoord, program); + if (dbg) { + debug("Actual:"); + var img = document.createElement("img"); + img.src = gl.canvas.toDataURL("image/png"); + var output = document.getElementById("console"); + output.appendChild(img); + } + } + } + } + } + } + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image.js new file mode 100644 index 000000000..eb7bb6a00 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-image.js @@ -0,0 +1,277 @@ +/* +** Copyright (c) 2015 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var imgCanvas; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + var blueColor = [0, 0, 255]; + var cyanColor = [0, 255, 255]; + var imageURLs = [resourcePath + "red-green.png", + resourcePath + "red-green-blue-cyan-4x4.png"]; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking image elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + blueColor = [0, 0, 0]; + cyanColor = [0, 0, 0]; + break; + + case gl.RG: + case gl.RG_INTEGER: + blueColor = [0, 0, 0]; + cyanColor = [0, 255, 0]; + break; + + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + wtu.loadImagesAsync(imageURLs, runTest); + } + + function uploadImageToTexture(image, useTexSubImage3D, flipY, bindingTarget, + depth, sourceSubRectangle, unpackImageHeight) + { + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Disable any writes to the alpha channel + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); + var uploadWidth = image.width; + var uploadHeight = image.height; + if (sourceSubRectangle) { + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); + uploadWidth = sourceSubRectangle[2]; + uploadHeight = sourceSubRectangle[3]; + } + if (unpackImageHeight) { + gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight); + } + // Upload the image into the texture + if (useTexSubImage3D) { + // Initialize the texture to black first + gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, uploadWidth, uploadHeight, depth, + gl[pixelFormat], gl[pixelType], image); + } else { + gl.texImage3D(bindingTarget, 0, gl[internalFormat], uploadWidth, uploadHeight, depth, 0, + gl[pixelFormat], gl[pixelType], image); + } + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors from texture upload"); + } + + function runRedGreenTest(image) { + function runOneIteration(image, useTexSubImage3D, flipY, bindingTarget, topColor, bottomColor, program) + { + debug('Testing ' + (useTexSubImage3D ? 'texSubImage3D' : 'texImage3D') + + ' with flipY=' + flipY + ' bindingTarget=' + + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY')); + + uploadImageToTexture(image, useTexSubImage3D, flipY, bindingTarget, 1); + + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + // Check a few pixels near the top and bottom and make sure they have + // the right color. + debug("Checking lower left corner"); + wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor, + "shouldBe " + bottomColor); + debug("Checking upper left corner"); + wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor, + "shouldBe " + topColor); + } + + var cases = [ + { sub: false, flipY: true, topColor: redColor, bottomColor: greenColor }, + { sub: false, flipY: false, topColor: greenColor, bottomColor: redColor }, + { sub: true, flipY: true, topColor: redColor, bottomColor: greenColor }, + { sub: true, flipY: false, topColor: greenColor, bottomColor: redColor }, + ]; + + var program = tiu.setupTexturedQuadWith3D(gl, internalFormat); + for (var i in cases) { + runOneIteration(image, cases[i].sub, cases[i].flipY, gl.TEXTURE_3D, + cases[i].topColor, cases[i].bottomColor, program); + } + program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); + for (var i in cases) { + runOneIteration(image, cases[i].sub, cases[i].flipY, gl.TEXTURE_2D_ARRAY, + cases[i].topColor, cases[i].bottomColor, program); + } + } + + function runRedGreenBlueCyanTest(image) { + function runOneIteration(image, useTexSubImage3D, flipY, bindingTarget, + depth, sourceSubRectangle, unpackImageHeight, + rTextureCoord, topColor, bottomColor, program) + { + sourceSubRectangleString = ''; + if (sourceSubRectangle) { + sourceSubRectangleString = ' sourceSubRectangle=' + sourceSubRectangle; + } + unpackImageHeightString = ''; + if (unpackImageHeight) { + unpackImageHeightString = ' unpackImageHeight=' + unpackImageHeight; + } + debug('Testing ' + (useTexSubImage3D ? 'texSubImage3D' : 'texImage3D') + + ' with flipY=' + flipY + ' bindingTarget=' + + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') + + sourceSubRectangleString + ' depth=' + depth + unpackImageHeightString + + ' rTextureCoord=' + rTextureCoord); + + uploadImageToTexture(image, useTexSubImage3D, flipY, bindingTarget, + depth, sourceSubRectangle, unpackImageHeight); + var rCoordLocation = gl.getUniformLocation(program, 'uRCoord'); + if (!rCoordLocation) { + testFailed('Shader incorrectly set up; couldn\'t find uRCoord uniform'); + return; + } + gl.uniform1f(rCoordLocation, rTextureCoord); + + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + // Check a few pixels near the top and bottom and make sure they have + // the right color. + debug("Checking lower left corner"); + wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor, + "shouldBe " + bottomColor); + debug("Checking upper left corner"); + wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor, + "shouldBe " + topColor); + } + + var cases = [ + // No UNPACK_IMAGE_HEIGHT specified. + { flipY: false, sourceSubRectangle: [0, 0, 2, 2], depth: 2, rTextureCoord: 0.0, + topColor: redColor, bottomColor: redColor }, + { flipY: false, sourceSubRectangle: [0, 0, 2, 2], depth: 2, rTextureCoord: 1.0, + topColor: blueColor, bottomColor: blueColor }, + { flipY: true, sourceSubRectangle: [0, 0, 2, 2], depth: 2, rTextureCoord: 0.0, + topColor: blueColor, bottomColor: blueColor }, + { flipY: true, sourceSubRectangle: [0, 0, 2, 2], depth: 2, rTextureCoord: 1.0, + topColor: redColor, bottomColor: redColor }, + { flipY: false, sourceSubRectangle: [2, 0, 2, 2], depth: 2, rTextureCoord: 0.0, + topColor: greenColor, bottomColor: greenColor }, + { flipY: false, sourceSubRectangle: [2, 0, 2, 2], depth: 2, rTextureCoord: 1.0, + topColor: cyanColor, bottomColor: cyanColor }, + { flipY: true, sourceSubRectangle: [2, 0, 2, 2], depth: 2, rTextureCoord: 0.0, + topColor: cyanColor, bottomColor: cyanColor }, + { flipY: true, sourceSubRectangle: [2, 0, 2, 2], depth: 2, rTextureCoord: 1.0, + topColor: greenColor, bottomColor: greenColor }, + + // Use UNPACK_IMAGE_HEIGHT to skip some pixels. + { flipY: false, sourceSubRectangle: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0, + topColor: redColor, bottomColor: redColor }, + { flipY: false, sourceSubRectangle: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0, + topColor: blueColor, bottomColor: blueColor }, + { flipY: true, sourceSubRectangle: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0, + topColor: blueColor, bottomColor: blueColor }, + { flipY: true, sourceSubRectangle: [0, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0, + topColor: redColor, bottomColor: redColor }, + { flipY: false, sourceSubRectangle: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0, + topColor: greenColor, bottomColor: greenColor }, + { flipY: false, sourceSubRectangle: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0, + topColor: cyanColor, bottomColor: cyanColor }, + { flipY: true, sourceSubRectangle: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 0.0, + topColor: cyanColor, bottomColor: cyanColor }, + { flipY: true, sourceSubRectangle: [2, 0, 1, 1], depth: 2, unpackImageHeight: 2, rTextureCoord: 1.0, + topColor: greenColor, bottomColor: greenColor }, + ]; + + var program = tiu.setupTexturedQuadWith3D(gl, internalFormat); + for (var i in cases) { + runOneIteration(image, false, cases[i].flipY, gl.TEXTURE_3D, + cases[i].depth, cases[i].sourceSubRectangle, + cases[i].unpackImageHeight, cases[i].rTextureCoord, + cases[i].topColor, cases[i].bottomColor, + program); + runOneIteration(image, true, cases[i].flipY, gl.TEXTURE_3D, + cases[i].depth, cases[i].sourceSubRectangle, + cases[i].unpackImageHeight, cases[i].rTextureCoord, + cases[i].topColor, cases[i].bottomColor, + program); + } + + program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); + for (var i in cases) { + runOneIteration(image, false, cases[i].flipY, gl.TEXTURE_2D_ARRAY, + cases[i].depth, cases[i].sourceSubRectangle, + cases[i].unpackImageHeight, cases[i].rTextureCoord, + cases[i].topColor, cases[i].bottomColor, + program); + runOneIteration(image, true, cases[i].flipY, gl.TEXTURE_2D_ARRAY, + cases[i].depth, cases[i].sourceSubRectangle, + cases[i].unpackImageHeight, cases[i].rTextureCoord, + cases[i].topColor, cases[i].bottomColor, + program); + } + } + + function runTest(imageMap) + { + runRedGreenTest(imageMap[imageURLs[0]]); + runRedGreenBlueCyanTest(imageMap[imageURLs[1]]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-svg-image.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-svg-image.js new file mode 100644 index 000000000..c940a601a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-svg-image.js @@ -0,0 +1,121 @@ +/* +** Copyright (c) 2015 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var imgCanvas; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking SVG image elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + break; + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + wtu.loadTexture(gl, resourcePath + "red-green.svg", runTest); + } + + function runOneIteration(image, flipY, topColor, bottomColor, bindingTarget, program) + { + debug('Testing ' + ' with flipY=' + flipY + ' bindingTarget=' + + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY')); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Disable any writes to the alpha channel + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);'); + // Upload the image into the texture + // Initialize the texture to black first + gl.texImage3D(bindingTarget, 0, gl[internalFormat], image.width, image.height, 1 /* depth */, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, image.width, image.height, 1 /* depth */, + gl[pixelFormat], gl[pixelType], image); + + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + // Check a few pixels near the top and bottom and make sure they have + // the right color. + debug("Checking lower left corner"); + wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor, + "shouldBe " + bottomColor); + debug("Checking upper left corner"); + wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor, + "shouldBe " + topColor); + } + + function runTest(image) + { + var program = tiu.setupTexturedQuadWith3D(gl, internalFormat); + runTestOnBindingTarget(image, gl.TEXTURE_3D, program); + program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); + runTestOnBindingTarget(image, gl.TEXTURE_2D_ARRAY, program); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + } + + function runTestOnBindingTarget(image, bindingTarget, program) { + var cases = [ + { flipY: true, topColor: redColor, bottomColor: greenColor }, + { flipY: false, topColor: greenColor, bottomColor: redColor }, + ]; + for (var i in cases) { + runOneIteration(image, cases[i].flipY, + cases[i].topColor, cases[i].bottomColor, + bindingTarget, program); + } + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-video.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-video.js new file mode 100644 index 000000000..3495bf17f --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-video.js @@ -0,0 +1,260 @@ +/* +** Copyright (c) 2015 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. +*/ + +// This block needs to be outside the onload handler in order for this +// test to run reliably in WebKit's test harness (at least the +// Chromium port). https://bugs.webkit.org/show_bug.cgi?id=87448 +initTestingHarness(); + +var old = debug; +var debug = function(msg) { + bufferedLogToConsole(msg); + old(msg); +}; + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + + // Test each format separately because many browsers implement each + // differently. Some might be GPU accelerated, some might not. Etc... + var videos = [ + { src: resourcePath + "red-green.mp4" , type: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', }, + { src: resourcePath + "red-green.webmvp9.webm", type: 'video/webm; codecs="vp9"', }, + { src: resourcePath + "red-green.webmvp8.webm", type: 'video/webm; codecs="vp8, vorbis"', }, + { src: resourcePath + "red-green.theora.ogv", type: 'video/ogg; codecs="theora, vorbis"', }, + ]; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking video elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + break; + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + runTest(); + } + + function runOneIteration(videoElement, flipY, useTexSubImage3D, topColor, bottomColor, program, bindingTarget, + depth, sourceSubRectangle, unpackImageHeight, rTextureCoord) + { + debug('Testing ' + + (useTexSubImage3D ? "texSubImage3D" : "texImage3D") + + ' with flipY=' + flipY + ' bindingTarget=' + + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') + + (sourceSubRectangle ? ', sourceSubRectangle=' + sourceSubRectangle : '') + + (unpackImageHeight ? ', unpackImageHeight=' + unpackImageHeight : '') + + ', depth=' + depth + + ', rTextureCoord=' + rTextureCoord); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Disable any writes to the alpha channel + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); + var uploadWidth = videoElement.width; + var uploadHeight = videoElement.height; + if (sourceSubRectangle) { + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); + uploadWidth = sourceSubRectangle[2]; + uploadHeight = sourceSubRectangle[3]; + } + if (unpackImageHeight) { + gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight); + } + // Upload the videoElement into the texture + if (useTexSubImage3D) { + // Initialize the texture to black first + gl.texImage3D(bindingTarget, 0, gl[internalFormat], + uploadWidth, uploadHeight, depth, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, + uploadWidth, uploadHeight, depth, + gl[pixelFormat], gl[pixelType], videoElement); + } else { + gl.texImage3D(bindingTarget, 0, gl[internalFormat], + uploadWidth, uploadHeight, depth, 0, + gl[pixelFormat], gl[pixelType], videoElement); + } + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0); + + var c = document.createElement("canvas"); + c.width = 16; + c.height = 16; + c.style.border = "1px solid black"; + var ctx = c.getContext("2d"); + ctx.drawImage(videoElement, 0, 0, 16, 16); + document.body.appendChild(c); + + var rCoordLocation = gl.getUniformLocation(program, 'uRCoord'); + if (!rCoordLocation) { + testFailed('Shader incorrectly set up; couldn\'t find uRCoord uniform'); + return; + } + gl.uniform1f(rCoordLocation, rTextureCoord); + + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + // Check a few pixels near the top and bottom and make sure they have + // the right color. + var tolerance = 5; + debug("Checking lower left corner"); + wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor, + "shouldBe " + bottomColor, tolerance); + debug("Checking upper left corner"); + wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor, + "shouldBe " + topColor, tolerance); + } + + function runTest(videoElement) + { + var cases = [ + // No UNPACK_IMAGE_HEIGHT specified. + { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 5, rTextureCoord: 0, + topColor: redColor, bottomColor: redColor }, + // Note that an rTextureCoord of 4.0 satisfies the need to + // have it be >= 1.0 for the TEXTURE_3D case, and also its + // use as an index in the TEXTURE_2D_ARRAY case. + { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 5, rTextureCoord: 4, + topColor: greenColor, bottomColor: greenColor }, + { flipY: false, sourceSubRectangle: [24, 48, 32, 32], depth: 1, rTextureCoord: 0, + topColor: greenColor, bottomColor: redColor }, + { flipY: true, sourceSubRectangle: [24, 48, 32, 32], depth: 1, rTextureCoord: 0, + topColor: redColor, bottomColor: greenColor }, + + // Use UNPACK_IMAGE_HEIGHT to skip some pixels. + { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 2, unpackImageHeight: 64, rTextureCoord: 0, + topColor: redColor, bottomColor: redColor }, + { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 2, unpackImageHeight: 64, rTextureCoord: 1, + topColor: greenColor, bottomColor: greenColor }, + ]; + + function runTexImageTest(bindingTarget) { + var program; + if (bindingTarget == gl.TEXTURE_3D) { + program = tiu.setupTexturedQuadWith3D(gl, internalFormat); + } else { + program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); + } + + return new Promise(function(resolve, reject) { + var videoNdx = 0; + var video; + function runNextVideo() { + if (video) { + video.pause(); + } + + if (videoNdx == videos.length) { + resolve("SUCCESS"); + return; + } + + var info = videos[videoNdx++]; + debug(""); + debug("testing: " + info.type); + video = document.createElement("video"); + var canPlay = true; + if (!video.canPlayType) { + testFailed("video.canPlayType required method missing"); + runNextVideo(); + return; + } + + if(!video.canPlayType(info.type).replace(/no/, '')) { + debug(info.type + " unsupported"); + runNextVideo(); + return; + }; + + document.body.appendChild(video); + video.type = info.type; + video.src = info.src; + wtu.startPlayingAndWaitForVideo(video, runTest); + } + function runTest() { + for (var i in cases) { + runOneIteration(video, cases[i].flipY, false, + cases[i].topColor, cases[i].bottomColor, + program, bindingTarget, cases[i].depth, + cases[i].sourceSubRectangle, + cases[i].unpackImageHeight, + cases[i].rTextureCoord); + runOneIteration(video, cases[i].flipY, true, + cases[i].topColor, cases[i].bottomColor, + program, bindingTarget, cases[i].depth, + cases[i].sourceSubRectangle, + cases[i].unpackImageHeight, + cases[i].rTextureCoord); + } + runNextVideo(); + } + runNextVideo(); + }); + } + + runTexImageTest(gl.TEXTURE_3D).then(function(val) { + runTexImageTest(gl.TEXTURE_2D_ARRAY).then(function(val) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + }); + }); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js new file mode 100644 index 000000000..f9415cf85 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-3d-with-webgl-canvas.js @@ -0,0 +1,204 @@ +/* +** Copyright (c) 2015 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. +*/ + +function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { + var wtu = WebGLTestUtils; + var tiu = TexImageUtils; + var gl = null; + var successfullyParsed = false; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + + function init() + { + description('Verify texImage3D and texSubImage3D code paths taking webgl canvas elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); + + // Set the default context version while still allowing the webglVersion URL query string to override it. + wtu.setDefault3DContextVersion(defaultContextVersion); + gl = wtu.create3DContext("example"); + + if (!prologue(gl)) { + finishTest(); + return; + } + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + break; + default: + break; + } + + gl.clearColor(0,0,0,1); + gl.clearDepth(1); + + runTest(); + } + + function setCanvasToRedGreen(ctx) { + var width = ctx.canvas.width; + var height = ctx.canvas.height; + var halfHeight = Math.floor(height / 2); + + ctx.viewport(0, 0, width, height); + + ctx.enable(ctx.SCISSOR_TEST); + ctx.scissor(0, 0, width, halfHeight); + ctx.clearColor(1.0, 0, 0, 1.0); + ctx.clear(ctx.COLOR_BUFFER_BIT); + ctx.scissor(0, halfHeight, width, height - halfHeight); + ctx.clearColor(0.0, 1.0, 0, 1.0); + ctx.clear(ctx.COLOR_BUFFER_BIT); + ctx.disable(ctx.SCISSOR_TEST); + } + + function setCanvasTo257x257(ctx, bindingTarget) { + ctx.canvas.width = 257; + ctx.canvas.height = 257; + setCanvasToRedGreen(ctx); + } + + function setCanvasToMin(ctx, bindingTarget) { + ctx.canvas.width = 1; + ctx.canvas.height = 2; + setCanvasToRedGreen(ctx); + } + + function runOneIteration(canvas, flipY, program, bindingTarget, opt_texture) + { + debug('Testing ' + flipY + ' bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') + + ' canvas size: ' + canvas.width + 'x' + canvas.height + ' with red-green'); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + if (!opt_texture) { + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } else { + var texture = opt_texture; + } + // Set up pixel store parameters + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); + wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);'); + + // Upload the image into the texture + // Initialize the texture to black first + gl.texImage3D(bindingTarget, 0, gl[internalFormat], canvas.width, canvas.height, 1 /* depth */, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, canvas.width, canvas.height, 1 /* depth */, + gl[pixelFormat], gl[pixelType], canvas); + + var width = gl.canvas.width; + var height = gl.canvas.height; + var halfHeight = Math.floor(height / 2); + var top = flipY ? (height - halfHeight) : 0; + var bottom = flipY ? 0 : (height - halfHeight); + + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]); + + // Check the top and bottom halves and make sure they have the right color. + debug("Checking " + (flipY ? "top" : "bottom")); + wtu.checkCanvasRect(gl, 0, bottom, width, halfHeight, redColor, "shouldBe " + redColor); + debug("Checking " + (flipY ? "bottom" : "top")); + wtu.checkCanvasRect(gl, 0, top, width, halfHeight, greenColor, "shouldBe " + greenColor); + + if (false) { + var ma = wtu.makeImageFromCanvas(canvas); + document.getElementById("console").appendChild(ma); + + var m = wtu.makeImageFromCanvas(gl.canvas); + document.getElementById("console").appendChild(m); + document.getElementById("console").appendChild(document.createElement("hr")); + } + + return texture; + } + + function runTest() + { + var ctx = wtu.create3DContext(); + var canvas = ctx.canvas; + + var cases = [ + { flipY: true, init: setCanvasToMin }, + { flipY: false }, + { flipY: true, init: setCanvasTo257x257 }, + { flipY: false }, + ]; + + function runTexImageTest(bindingTarget) { + var program; + if (bindingTarget == gl.TEXTURE_3D) { + program = tiu.setupTexturedQuadWith3D(gl, internalFormat); + } else { + program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); + } + + return new Promise(function(resolve, reject) { + var count = 4; + var caseNdx = 0; + var texture = undefined; + function runNextTest() { + var c = cases[caseNdx]; + if (c.init) { + c.init(ctx, bindingTarget); + } + texture = runOneIteration(canvas, c.flipY, program, bindingTarget, texture); + // for the first 2 iterations always make a new texture. + if (count > 2) { + texture = undefined; + } + ++caseNdx; + if (caseNdx == cases.length) { + caseNdx = 0; + --count; + if (!count) { + resolve("SUCCESS"); + return; + } + } + wtu.waitForComposite(runNextTest); + } + runNextTest(); + }); + } + + runTexImageTest(gl.TEXTURE_3D).then(function(val) { + runTexImageTest(gl.TEXTURE_2D_ARRAY).then(function(val) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + finishTest(); + }); + }); + } + + return init; +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-utils.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-utils.js new file mode 100644 index 000000000..ba5be49a9 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-utils.js @@ -0,0 +1,818 @@ +/* +** Copyright (c) 2015 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. +*/ +var TexImageUtils = (function() { + + "use strict"; + + var wtu = WebGLTestUtils; + + /** + * A vertex shader for a single texture. + * @type {string} + */ + var simpleTextureVertexShaderES3 = [ + '#version 300 es', + 'in vec4 vPosition;', + 'in vec2 texCoord0;', + 'out vec2 texCoord;', + 'void main() {', + ' gl_Position = vPosition;', + ' texCoord = texCoord0;', + '}'].join('\n'); + + /** + * A fragment shader for a single unsigned integer texture. + * @type {string} + */ + // Note we always output 1.0 for alpha because if the texture does not contain + // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255]. + var simpleUintTextureFragmentShaderES3 = [ + '#version 300 es', + 'precision mediump float;', + 'uniform mediump usampler2D tex;', + 'in vec2 texCoord;', + 'out vec4 fragData;', + 'void main() {', + ' uvec4 data = texture(tex, texCoord);', + ' fragData = vec4(float(data[0])/255.0,', + ' float(data[1])/255.0,', + ' float(data[2])/255.0,', + ' 1.0);', + '}'].join('\n'); + + /** + * A fragment shader for a single signed integer texture. + * @type {string} + */ + // Note we always output 1.0 for alpha because if the texture does not contain + // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255]. + var simpleIntTextureFragmentShaderES3 = [ + '#version 300 es', + 'precision mediump float;', + 'uniform mediump isampler2D tex;', + 'in vec2 texCoord;', + 'out vec4 fragData;', + 'void main() {', + ' ivec4 data = texture(tex, texCoord);', + ' fragData = vec4(float(data[0])/255.0,', + ' float(data[1])/255.0,', + ' float(data[2])/255.0,', + ' 1.0);', + '}'].join('\n'); + + /** + * A fragment shader for a single cube map unsigned integer texture. + * @type {string} + */ + // Note we always output 1.0 for alpha because if the texture does not contain + // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255]. + var simpleCubeMapUintTextureFragmentShaderES3 = [ + '#version 300 es', + 'precision mediump float;', + 'uniform mediump usamplerCube tex;', + 'uniform int face;', + 'in vec2 texCoord;', + 'out vec4 fragData;', + 'void main() {', + // Transform [0, 1] -> [-1, 1] + ' vec2 texC2 = (texCoord * 2.) - 1.;', + // Transform 2d tex coord. to each face of TEXTURE_CUBE_MAP coord. + ' vec3 texCube = vec3(0., 0., 0.);', + ' if (face == 34069) {', // TEXTURE_CUBE_MAP_POSITIVE_X + ' texCube = vec3(1., -texC2.y, -texC2.x);', + ' } else if (face == 34070) {', // TEXTURE_CUBE_MAP_NEGATIVE_X + ' texCube = vec3(-1., -texC2.y, texC2.x);', + ' } else if (face == 34071) {', // TEXTURE_CUBE_MAP_POSITIVE_Y + ' texCube = vec3(texC2.x, 1., texC2.y);', + ' } else if (face == 34072) {', // TEXTURE_CUBE_MAP_NEGATIVE_Y + ' texCube = vec3(texC2.x, -1., -texC2.y);', + ' } else if (face == 34073) {', // TEXTURE_CUBE_MAP_POSITIVE_Z + ' texCube = vec3(texC2.x, -texC2.y, 1.);', + ' } else if (face == 34074) {', // TEXTURE_CUBE_MAP_NEGATIVE_Z + ' texCube = vec3(-texC2.x, -texC2.y, -1.);', + ' }', + ' uvec4 data = texture(tex, texCube);', + ' fragData = vec4(float(data[0])/255.0,', + ' float(data[1])/255.0,', + ' float(data[2])/255.0,', + ' 1.0);', + '}'].join('\n'); + + /** + * A fragment shader for a single cube map signed integer texture. + * @type {string} + */ + // Note we always output 1.0 for alpha because if the texture does not contain + // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255]. + var simpleCubeMapIntTextureFragmentShaderES3 = [ + '#version 300 es', + 'precision mediump float;', + 'uniform mediump isamplerCube tex;', + 'uniform int face;', + 'in vec2 texCoord;', + 'out vec4 fragData;', + 'void main() {', + // Transform [0, 1] -> [-1, 1] + ' vec2 texC2 = (texCoord * 2.) - 1.;', + // Transform 2d tex coord. to each face of TEXTURE_CUBE_MAP coord. + ' vec3 texCube = vec3(0., 0., 0.);', + ' if (face == 34069) {', // TEXTURE_CUBE_MAP_POSITIVE_X + ' texCube = vec3(1., -texC2.y, -texC2.x);', + ' } else if (face == 34070) {', // TEXTURE_CUBE_MAP_NEGATIVE_X + ' texCube = vec3(-1., -texC2.y, texC2.x);', + ' } else if (face == 34071) {', // TEXTURE_CUBE_MAP_POSITIVE_Y + ' texCube = vec3(texC2.x, 1., texC2.y);', + ' } else if (face == 34072) {', // TEXTURE_CUBE_MAP_NEGATIVE_Y + ' texCube = vec3(texC2.x, -1., -texC2.y);', + ' } else if (face == 34073) {', // TEXTURE_CUBE_MAP_POSITIVE_Z + ' texCube = vec3(texC2.x, -texC2.y, 1.);', + ' } else if (face == 34074) {', // TEXTURE_CUBE_MAP_NEGATIVE_Z + ' texCube = vec3(-texC2.x, -texC2.y, -1.);', + ' }', + ' ivec4 data = texture(tex, texCube);', + ' fragData = vec4(float(data[0])/255.0,', + ' float(data[1])/255.0,', + ' float(data[2])/255.0,', + ' 1.0);', + '}'].join('\n'); + + /** + * A fragment shader for a single 3D texture. + * @type {string} + */ + // Note that the tex coordinate r (the uniform uRCoord) is set to 0.0 by default. + var simple3DTextureFragmentShaderES3 = [ + '#version 300 es', + 'precision mediump float;', + 'uniform mediump sampler3D tex;', + 'in vec2 texCoord;', + 'uniform float uRCoord;', + 'out vec4 fragData;', + 'void main() {', + ' fragData = vec4(texture(tex, vec3(texCoord, uRCoord)).rgb, 1.0);', + '}'].join('\n'); + + /** + * A fragment shader for a single 3D unsigned integer texture. + * @type {string} + */ + // Note that the tex coordinate r (the uniform uRCoord) is set to 0.0 by default. + // Note we always output 1.0 for alpha because if the texture does not contain + // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255]. + var simple3DUintTextureFragmentShaderES3 = [ + '#version 300 es', + 'precision mediump float;', + 'uniform mediump usampler3D tex;', + 'in vec2 texCoord;', + 'uniform float uRCoord;', + 'out vec4 fragData;', + 'void main() {', + ' uvec4 data = texture(tex, vec3(texCoord, uRCoord));', + ' fragData = vec4(float(data[0])/255.0,', + ' float(data[1])/255.0,', + ' float(data[2])/255.0,', + ' 1.0);', + '}'].join('\n'); + + /** + * A fragment shader for a single 3D signed integer texture. + * @type {string} + */ + // Note that the tex coordinate r (the uniform uRCoord) is set to 0.0 by default. + // Note we always output 1.0 for alpha because if the texture does not contain + // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255]. + var simple3DIntTextureFragmentShaderES3 = [ + '#version 300 es', + 'precision mediump float;', + 'uniform mediump isampler3D tex;', + 'in vec2 texCoord;', + 'uniform float uRCoord;', + 'out vec4 fragData;', + 'void main() {', + ' ivec4 data = texture(tex, vec3(texCoord, uRCoord));', + ' fragData = vec4(float(data[0])/255.0,', + ' float(data[1])/255.0,', + ' float(data[2])/255.0,', + ' 1.0);', + '}'].join('\n'); + + /** + * A fragment shader for a single 2D_ARRAY texture. + * @type {string} + */ + // Note that the first image in the array (selected by the uniform + // uRCoord) is used by default. + var simple2DArrayTextureFragmentShaderES3 = [ + '#version 300 es', + 'precision mediump float;', + 'uniform mediump sampler2DArray tex;', + 'in vec2 texCoord;', + 'uniform float uRCoord;', + 'out vec4 fragData;', + 'void main() {', + ' fragData = vec4(texture(tex, vec3(texCoord, uRCoord)).rgb, 1.0);', + '}'].join('\n'); + + /** + * A fragment shader for a single 2D_ARRAY unsigned integer texture. + * @type {string} + */ + // Note that the first image in the array (selected by the uniform + // uRCoord) is used by default. + // Note we always output 1.0 for alpha because if the texture does not contain + // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255]. + var simple2DArrayUintTextureFragmentShaderES3 = [ + '#version 300 es', + 'precision mediump float;', + 'uniform mediump usampler2DArray tex;', + 'in vec2 texCoord;', + 'uniform float uRCoord;', + 'out vec4 fragData;', + 'void main() {', + ' uvec4 data = texture(tex, vec3(texCoord, uRCoord));', + ' fragData = vec4(float(data[0])/255.0,', + ' float(data[1])/255.0,', + ' float(data[2])/255.0,', + ' 1.0);', + '}'].join('\n'); + + /** + * A fragment shader for a single 2D_ARRAY signed integer texture. + * @type {string} + */ + // Note that the first image in the array (selected by the uniform + // uRCoord) is used by default. + // Note we always output 1.0 for alpha because if the texture does not contain + // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255]. + var simple2DArrayIntTextureFragmentShaderES3 = [ + '#version 300 es', + 'precision mediump float;', + 'uniform mediump isampler2DArray tex;', + 'in vec2 texCoord;', + 'uniform float uRCoord;', + 'out vec4 fragData;', + 'void main() {', + ' ivec4 data = texture(tex, vec3(texCoord, uRCoord));', + ' fragData = vec4(float(data[0])/255.0,', + ' float(data[1])/255.0,', + ' float(data[2])/255.0,', + ' 1.0);', + '}'].join('\n'); + + + /** + * Creates a simple texture vertex shader. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLShader} + */ + var setupSimpleTextureVertexShader = function(gl) { + return WebGLTestUtils.loadShader(gl, simpleTextureVertexShaderES3, gl.VERTEX_SHADER); + }; + + /** + * Creates a simple unsigned integer texture fragment shader. + * Output is scaled by 1/255 to bring the result into normalized float range. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLShader} + */ + var setupSimpleUintTextureFragmentShader = function(gl) { + return WebGLTestUtils.loadShader(gl, simpleUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER); + }; + + /** + * Creates a simple signed integer texture fragment shader. + * Output is scaled by 1/255 to bring the result into normalized float range. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLShader} + */ + var setupSimpleIntTextureFragmentShader = function(gl) { + return WebGLTestUtils.loadShader(gl, simpleIntTextureFragmentShaderES3, gl.FRAGMENT_SHADER); + }; + + /** + * Creates a simple cube map unsigned integer texture fragment shader. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLShader} + */ + var setupSimpleCubeMapUintTextureFragmentShader = function(gl) { + return WebGLTestUtils.loadShader(gl, simpleCubeMapUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER); + }; + + /** + * Creates a simple cube map signed integer texture fragment shader. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLShader} + */ + var setupSimpleCubeMapIntTextureFragmentShader = function(gl) { + return WebGLTestUtils.loadShader(gl, simpleCubeMapIntTextureFragmentShaderES3, gl.FRAGMENT_SHADER); + }; + + /** + * Creates a simple 3D texture fragment shader. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLShader} + */ + var setupSimple3DTextureFragmentShader = function(gl) { + return WebGLTestUtils.loadShader(gl, simple3DTextureFragmentShaderES3, gl.FRAGMENT_SHADER); + }; + + /** + * Creates a simple 3D unsigned integer texture fragment shader. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLShader} + */ + var setupSimple3DUintTextureFragmentShader = function(gl) { + return WebGLTestUtils.loadShader(gl, simple3DUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER); + }; + + /** + * Creates a simple 3D signed integer texture fragment shader. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLShader} + */ + var setupSimple3DIntTextureFragmentShader = function(gl) { + return WebGLTestUtils.loadShader(gl, simple3DIntTextureFragmentShaderES3, gl.FRAGMENT_SHADER); + }; + + /** + * Creates a simple 2D_ARRAY texture fragment shader. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLShader} + */ + var setupSimple2DArrayTextureFragmentShader = function(gl) { + return WebGLTestUtils.loadShader(gl, simple2DArrayTextureFragmentShaderES3, gl.FRAGMENT_SHADER); + }; + + /** + * Creates a simple 2D_ARRAY integer texture fragment shader. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLShader} + */ + var setupSimple2DArrayUintTextureFragmentShader = function(gl) { + return WebGLTestUtils.loadShader(gl, simple2DArrayUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER); + }; + + /** + * Creates a simple unsigned integer texture program. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} opt_positionLocation The attrib location for position. + * @param {number} opt_texcoordLocation The attrib location for texture coords. + * @return {WebGLProgram} + */ + var setupSimpleUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) + { + opt_positionLocation = opt_positionLocation || 0; + opt_texcoordLocation = opt_texcoordLocation || 1; + var vs = setupSimpleTextureVertexShader(gl), + fs = setupSimpleUintTextureFragmentShader(gl); + if (!vs || !fs) { + return null; + } + var program = WebGLTestUtils.setupProgram( + gl, + [vs, fs], + ['vPosition', 'texCoord0'], + [opt_positionLocation, opt_texcoordLocation]); + if (!program) { + gl.deleteShader(fs); + gl.deleteShader(vs); + } + gl.useProgram(program); + return program; + }; + + /** + * Creates a simple signed integer texture program. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} opt_positionLocation The attrib location for position. + * @param {number} opt_texcoordLocation The attrib location for texture coords. + * @return {WebGLProgram} + */ + var setupSimpleIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) + { + opt_positionLocation = opt_positionLocation || 0; + opt_texcoordLocation = opt_texcoordLocation || 1; + var vs = setupSimpleTextureVertexShader(gl), + fs = setupSimpleIntTextureFragmentShader(gl); + if (!vs || !fs) { + return null; + } + var program = WebGLTestUtils.setupProgram( + gl, + [vs, fs], + ['vPosition', 'texCoord0'], + [opt_positionLocation, opt_texcoordLocation]); + if (!program) { + gl.deleteShader(fs); + gl.deleteShader(vs); + } + gl.useProgram(program); + return program; + }; + + /** + * Creates a simple cube map unsigned integer texture program. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} opt_positionLocation The attrib location for position. + * @param {number} opt_texcoordLocation The attrib location for texture coords. + * @return {WebGLProgram} + */ + var setupSimpleCubeMapUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) { + opt_positionLocation = opt_positionLocation || 0; + opt_texcoordLocation = opt_texcoordLocation || 1; + var vs = setupSimpleTextureVertexShader(gl); + var fs = setupSimpleCubeMapUintTextureFragmentShader(gl); + if (!vs || !fs) { + return null; + } + var program = WebGLTestUtils.setupProgram( + gl, + [vs, fs], + ['vPosition', 'texCoord0'], + [opt_positionLocation, opt_texcoordLocation]); + if (!program) { + gl.deleteShader(fs); + gl.deleteShader(vs); + } + gl.useProgram(program); + return program; + }; + + /** + * Creates a simple cube map signed integer texture program. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} opt_positionLocation The attrib location for position. + * @param {number} opt_texcoordLocation The attrib location for texture coords. + * @return {WebGLProgram} + */ + var setupSimpleCubeMapIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) { + opt_positionLocation = opt_positionLocation || 0; + opt_texcoordLocation = opt_texcoordLocation || 1; + var vs = setupSimpleTextureVertexShader(gl); + var fs = setupSimpleCubeMapIntTextureFragmentShader(gl); + if (!vs || !fs) { + return null; + } + var program = WebGLTestUtils.setupProgram( + gl, + [vs, fs], + ['vPosition', 'texCoord0'], + [opt_positionLocation, opt_texcoordLocation]); + if (!program) { + gl.deleteShader(fs); + gl.deleteShader(vs); + } + gl.useProgram(program); + return program; + }; + + /** + * Creates a simple 3D texture program. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} opt_positionLocation The attrib location for position. + * @param {number} opt_texcoordLocation The attrib location for texture coords. + * @return {WebGLProgram} + */ + var setupSimple3DTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) + { + opt_positionLocation = opt_positionLocation || 0; + opt_texcoordLocation = opt_texcoordLocation || 1; + var vs = setupSimpleTextureVertexShader(gl), + fs = setupSimple3DTextureFragmentShader(gl); + if (!vs || !fs) { + return null; + } + var program = WebGLTestUtils.setupProgram( + gl, + [vs, fs], + ['vPosition', 'texCoord0'], + [opt_positionLocation, opt_texcoordLocation]); + if (!program) { + gl.deleteShader(fs); + gl.deleteShader(vs); + } + gl.useProgram(program); + return program; + }; + + /** + * Creates a simple 3D unsigned integer texture program. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} opt_positionLocation The attrib location for position. + * @param {number} opt_texcoordLocation The attrib location for texture coords. + * @return {WebGLProgram} + */ + var setupSimple3DUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) + { + opt_positionLocation = opt_positionLocation || 0; + opt_texcoordLocation = opt_texcoordLocation || 1; + var vs = setupSimpleTextureVertexShader(gl), + fs = setupSimple3DUintTextureFragmentShader(gl); + if (!vs || !fs) { + return null; + } + var program = WebGLTestUtils.setupProgram( + gl, + [vs, fs], + ['vPosition', 'texCoord0'], + [opt_positionLocation, opt_texcoordLocation]); + if (!program) { + gl.deleteShader(fs); + gl.deleteShader(vs); + } + gl.useProgram(program); + return program; + }; + + /** + * Creates a simple 3D signed integer texture program. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} opt_positionLocation The attrib location for position. + * @param {number} opt_texcoordLocation The attrib location for texture coords. + * @return {WebGLProgram} + */ + var setupSimple3DIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) + { + opt_positionLocation = opt_positionLocation || 0; + opt_texcoordLocation = opt_texcoordLocation || 1; + var vs = setupSimpleTextureVertexShader(gl), + fs = setupSimple3DIntTextureFragmentShader(gl); + if (!vs || !fs) { + return null; + } + var program = WebGLTestUtils.setupProgram( + gl, + [vs, fs], + ['vPosition', 'texCoord0'], + [opt_positionLocation, opt_texcoordLocation]); + if (!program) { + gl.deleteShader(fs); + gl.deleteShader(vs); + } + gl.useProgram(program); + return program; + }; + + /** + * Creates a simple 2D_ARRAY texture program. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} opt_positionLocation The attrib location for position. + * @param {number} opt_texcoordLocation The attrib location for texture coords. + * @return {WebGLProgram} + */ + var setupSimple2DArrayTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) + { + opt_positionLocation = opt_positionLocation || 0; + opt_texcoordLocation = opt_texcoordLocation || 1; + var vs = setupSimpleTextureVertexShader(gl), + fs = setupSimple2DArrayTextureFragmentShader(gl); + if (!vs || !fs) { + return null; + } + var program = WebGLTestUtils.setupProgram( + gl, + [vs, fs], + ['vPosition', 'texCoord0'], + [opt_positionLocation, opt_texcoordLocation]); + if (!program) { + gl.deleteShader(fs); + gl.deleteShader(vs); + } + gl.useProgram(program); + return program; + }; + + /** + * Creates a simple 2D_ARRAY unsigned integer texture program. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} opt_positionLocation The attrib location for position. + * @param {number} opt_texcoordLocation The attrib location for texture coords. + * @return {WebGLProgram} + */ + var setupSimple2DArrayUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) + { + opt_positionLocation = opt_positionLocation || 0; + opt_texcoordLocation = opt_texcoordLocation || 1; + var vs = setupSimpleTextureVertexShader(gl), + fs = setupSimple2DArrayUintTextureFragmentShader(gl); + if (!vs || !fs) { + return null; + } + var program = WebGLTestUtils.setupProgram( + gl, + [vs, fs], + ['vPosition', 'texCoord0'], + [opt_positionLocation, opt_texcoordLocation]); + if (!program) { + gl.deleteShader(fs); + gl.deleteShader(vs); + } + gl.useProgram(program); + return program; + }; + + /** + * Creates a simple 2D_ARRAY signed integer texture program. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {number} opt_positionLocation The attrib location for position. + * @param {number} opt_texcoordLocation The attrib location for texture coords. + * @return {WebGLProgram} + */ + var setupSimple2DArrayIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) + { + opt_positionLocation = opt_positionLocation || 0; + opt_texcoordLocation = opt_texcoordLocation || 1; + var vs = setupSimpleTextureVertexShader(gl), + fs = setupSimple2DArrayIntTextureFragmentShader(gl); + if (!vs || !fs) { + return null; + } + var program = WebGLTestUtils.setupProgram( + gl, + [vs, fs], + ['vPosition', 'texCoord0'], + [opt_positionLocation, opt_texcoordLocation]); + if (!program) { + gl.deleteShader(fs); + gl.deleteShader(vs); + } + gl.useProgram(program); + return program; + }; + + /** + * Creates a program and buffers for rendering a unsigned integer textured quad. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLProgram} + */ + var setupUintTexturedQuad = function(gl) { + var program = setupSimpleUintTextureProgram(gl); + wtu.setupUnitQuad(gl); + return program; + }; + + /** + * Creates a program and buffers for rendering a signed integer textured quad. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLProgram} + */ + var setupIntTexturedQuad = function(gl) { + var program = setupSimpleIntTextureProgram(gl); + wtu.setupUnitQuad(gl); + return program; + }; + + /** + * Creates a program and buffers for rendering a textured quad with + * a cube map unsigned integer texture. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLProgram} + */ + var setupUintTexturedQuadWithCubeMap = function(gl) + { + var program = setupSimpleCubeMapUintTextureProgram(gl); + wtu.setupUnitQuad(gl); + return program; + }; + + /** + * Creates a program and buffers for rendering a textured quad with + * a cube map signed integer texture. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @return {!WebGLProgram} + */ + var setupIntTexturedQuadWithCubeMap = function(gl) + { + var program = setupSimpleCubeMapIntTextureProgram(gl); + wtu.setupUnitQuad(gl); + return program; + }; + + /** + * Does the GL internal format represent an unsigned integer format + * texture? + * @return {boolean} + */ + var isUintFormat = function(internalFormat) + { + return (internalFormat == "R8UI" || internalFormat == "RG8UI" || internalFormat == "RGB8UI" || internalFormat == "RGBA8UI" || + internalFormat == "R16UI" || internalFormat == "RG16UI" || internalFormat == "RGB16UI" || internalFormat == "RGBA16UI" || + internalFormat == "R32UI" || internalFormat == "RG32UI" || internalFormat == "RGB32UI" || internalFormat == "RGBA32UI"); + }; + + /** + * Does the GL internal format represent an signed integer format + * texture? + * @return {boolean} + */ + var isIntFormat = function(internalFormat) + { + return (internalFormat == "R8I" || internalFormat == "RG8I" || internalFormat == "RGB8I" || internalFormat == "RGBA8I" || + internalFormat == "R16I" || internalFormat == "RG16I" || internalFormat == "RGB16I" || internalFormat == "RGBA16I" || + internalFormat == "R32I" || internalFormat == "RG32I" || internalFormat == "RGB32I" || internalFormat == "RGBA32I"); + }; + + /** + * Createa a program and buffers for rendering a textured quad for + * tex-image-and-sub-image tests. Handle selection of correct + * program to handle texture format. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {string} internalFormat The internal format for texture to be tested. + */ + var setupTexturedQuad = function(gl, internalFormat) + { + if (isUintFormat(internalFormat)) + return setupUintTexturedQuad(gl); + if (isIntFormat(internalFormat)) + return setupIntTexturedQuad(gl); + return wtu.setupTexturedQuad(gl); + }; + + /** + * Createa a program and buffers for rendering a textured quad with + * a cube map for tex-image-and-sub-image tests. Handle selection of + * correct program to handle texture format. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {string} internalFormat The internal format for texture to be tested. + */ + function setupTexturedQuadWithCubeMap(gl, internalFormat) + { + if (isUintFormat(internalFormat)) + return setupUintTexturedQuadWithCubeMap(gl); + if (isIntFormat(internalFormat)) + return setupIntTexturedQuadWithCubeMap(gl); + return wtu.setupTexturedQuadWithCubeMap(gl); + } + + /** + * Createa a program and buffers for rendering a textured quad with a 3D texture + * for tex-image-and-sub-image tests. Handle selection of correct + * program to handle texture format. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {string} internalFormat The internal format for texture to be tested. + */ + var setupTexturedQuadWith3D = function(gl, internalFormat) + { + var program; + if (isUintFormat(internalFormat)) + program = setupSimple3DUintTextureProgram(gl); + else if (isIntFormat(internalFormat)) + program = setupSimple3DIntTextureProgram(gl); + else + program = setupSimple3DTextureProgram(gl); + var uRCoordLoc = gl.getUniformLocation(program, 'uRCoord'); + gl.uniform1f(uRCoordLoc, 0.0); + wtu.setupUnitQuad(gl); + return program; + }; + + /** + * Createa a program and buffers for rendering a textured quad with a 2D_ARRAY + * texture for tex-image-and-sub-image tests. Handle selection of correct + * program to handle texture format. + * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use. + * @param {string} internalFormat The internal format for texture to be tested. + */ + var setupTexturedQuadWith2DArray = function(gl, internalFormat) + { + var program; + if (isUintFormat(internalFormat)) + program = setupSimple2DArrayUintTextureProgram(gl); + else if (isIntFormat(internalFormat)) + program = setupSimple2DArrayIntTextureProgram(gl); + else + program = setupSimple2DArrayTextureProgram(gl); + var uRCoordLoc = gl.getUniformLocation(program, 'uRCoord'); + gl.uniform1f(uRCoordLoc, 0.0); + wtu.setupUnitQuad(gl); + return program; + }; + + return { + setupTexturedQuad: setupTexturedQuad, + setupTexturedQuadWithCubeMap: setupTexturedQuadWithCubeMap, + setupTexturedQuadWith3D: setupTexturedQuadWith3D, + setupTexturedQuadWith2DArray: setupTexturedQuadWith2DArray + }; + +}()); diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js new file mode 100644 index 000000000..af7f3d141 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-image-and-sub-image-with-image-bitmap-utils.js @@ -0,0 +1,408 @@ +/* +** 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. +*/ + + +function runOneIterationImageBitmapTest(useTexSubImage, bindingTarget, program, bitmap, flipY, premultiplyAlpha, optionsVal, + internalFormat, pixelFormat, pixelType, gl, tiu, wtu) +{ + var halfRed = [128, 0, 0]; + var halfGreen = [0, 128, 0]; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + var blackColor = [0, 0, 0]; + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + halfGreen = [0, 0, 0]; + break; + default: + break; + } + + switch (gl[internalFormat]) { + case gl.SRGB8: + case gl.SRGB8_ALPHA8: + // Math.pow((128 / 255 + 0.055) / 1.055, 2.4) * 255 = 55 + halfRed = [55, 0, 0]; + halfGreen = [0, 55, 0]; + break; + default: + break; + } + + var str; + if (optionsVal.is3D) { + str = 'Testing ' + (useTexSubImage ? 'texSubImage3D' : 'texImage3D') + + ' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha + + ', bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY'); + } else { + str = 'Testing ' + (useTexSubImage ? 'texSubImage2D' : 'texImage2D') + + ' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha + + ', bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP'); + } + debug(str); + bufferedLogToConsole(str); + + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Enable writes to the RGBA channels + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + var targets = [bindingTarget]; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, + gl.TEXTURE_CUBE_MAP_NEGATIVE_X, + gl.TEXTURE_CUBE_MAP_POSITIVE_Y, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, + gl.TEXTURE_CUBE_MAP_POSITIVE_Z, + gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; + } + + bufferedLogToConsole("Starts uploading the image into texture"); + // Upload the image into the texture + for (var tt = 0; tt < targets.length; ++tt) { + if (optionsVal.is3D) { + gl.texImage3D(targets[tt], 0, gl[internalFormat], bitmap.width, bitmap.height, 1 /* depth */, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage3D(targets[tt], 0, 0, 0, 0, bitmap.width, bitmap.height, 1, + gl[pixelFormat], gl[pixelType], bitmap); + } else { + if (useTexSubImage) { + // Initialize the texture to black first + gl.texImage2D(targets[tt], 0, gl[internalFormat], bitmap.width, bitmap.height, 0, + gl[pixelFormat], gl[pixelType], null); + gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], bitmap); + } else { + gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], bitmap); + } + } + } + bufferedLogToConsole("Uploading texture completed"); + + var width = gl.canvas.width; + var halfWidth = Math.floor(width / 2); + var quaterWidth = Math.floor(halfWidth / 2); + var height = gl.canvas.height; + var halfHeight = Math.floor(height / 2); + var quaterHeight = Math.floor(halfHeight / 2); + + var top = flipY ? quaterHeight : (height - halfHeight + quaterHeight); + var bottom = flipY ? (height - halfHeight + quaterHeight) : quaterHeight; + + var tl = redColor; + var tr = premultiplyAlpha ? ((optionsVal.alpha == 0.5) ? halfRed : (optionsVal.alpha == 1) ? redColor : blackColor) : redColor; + var bl = greenColor; + var br = premultiplyAlpha ? ((optionsVal.alpha == 0.5) ? halfGreen : (optionsVal.alpha == 1) ? greenColor : blackColor) : greenColor; + + var loc; + var skipCorner = false; + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + loc = gl.getUniformLocation(program, "face"); + switch (pixelFormat) { + case gl.RED_INTEGER: + case gl.RG_INTEGER: + case gl.RGB_INTEGER: + case gl.RGBA_INTEGER: + // https://github.com/KhronosGroup/WebGL/issues/1819 + skipCorner = true; + break; + } + } + + var tolerance = 10; + for (var tt = 0; tt < targets.length; ++tt) { + if (bindingTarget == gl.TEXTURE_CUBE_MAP) { + gl.uniform1i(loc, targets[tt]); + } + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + + // Check the top pixel and bottom pixel and make sure they have + // the right color. + bufferedLogToConsole("Checking " + (flipY ? "top" : "bottom")); + wtu.checkCanvasRect(gl, quaterWidth, bottom, 2, 2, tl, "shouldBe " + tl); + if (!skipCorner && !flipY) { + wtu.checkCanvasRect(gl, halfWidth + quaterWidth, bottom, 2, 2, tr, "shouldBe " + tr, tolerance); + } + bufferedLogToConsole("Checking " + (flipY ? "bottom" : "top")); + wtu.checkCanvasRect(gl, quaterWidth, top, 2, 2, bl, "shouldBe " + bl); + if (!skipCorner && flipY) { + wtu.checkCanvasRect(gl, halfWidth + quaterWidth, top, 2, 2, br, "shouldBe " + br, tolerance); + } + } + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); +} + +function resetUnpackParams(gl) +{ + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, 0); + gl.pixelStorei(gl.UNPACK_ROW_LENGTH, 0); + gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0); +} + +function runOneIterationImageBitmapTestSubSource(useTexSubImage, bindingTarget, program, bitmap, flipY, premultiplyAlpha, optionsVal, + internalFormat, pixelFormat, pixelType, gl, tiu, wtu) +{ + var halfRed = [128, 0, 0]; + var halfGreen = [0, 128, 0]; + var redColor = [255, 0, 0]; + var greenColor = [0, 255, 0]; + var blackColor = [0, 0, 0]; + + switch (gl[pixelFormat]) { + case gl.RED: + case gl.RED_INTEGER: + greenColor = [0, 0, 0]; + halfGreen = [0, 0, 0]; + break; + default: + break; + } + + switch (gl[internalFormat]) { + case gl.SRGB8: + case gl.SRGB8_ALPHA8: + // Math.pow((128 / 255 + 0.055) / 1.055, 2.4) * 255 = 55 + halfRed = [55, 0, 0]; + halfGreen = [0, 55, 0]; + break; + default: + break; + } + + var str; + if (optionsVal.is3D) { + str = 'Testing ' + (useTexSubImage ? 'texSubImage3D' : 'texImage3D') + '[SubSource]' + + ' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha + + ', bindingTarget=TEXTURE_3D'; + } else { + str = 'Testing ' + (useTexSubImage ? 'texSubImage2D' : 'texImage2D') + '[SubSource]' + + ' with flipY=' + flipY + ', premultiplyAlpha=' + premultiplyAlpha + + ', bindingTarget=TEXTURE_2D'; + } + debug(str); + bufferedLogToConsole(str); + + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + // Enable writes to the RGBA channels + gl.colorMask(1, 1, 1, 0); + var texture = gl.createTexture(); + // Bind the texture to texture unit 0 + gl.bindTexture(bindingTarget, texture); + // Set up texture parameters + gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + var srcTL = redColor; + var srcTR = premultiplyAlpha ? ((optionsVal.alpha == 0.5) ? halfRed : (optionsVal.alpha == 1) ? redColor : blackColor) : redColor; + var srcBL = greenColor; + var srcBR = premultiplyAlpha ? ((optionsVal.alpha == 0.5) ? halfGreen : (optionsVal.alpha == 1) ? greenColor : blackColor) : greenColor; + + var tl, tr, bl, br; + + bufferedLogToConsole("Starts uploading the image into texture"); + // Upload the image into the texture + if (optionsVal.is3D) { + if (useTexSubImage) { + // Initialize the texture to black first + gl.texImage3D(bindingTarget, 0, gl[internalFormat], bitmap.width, bitmap.height, 1 /* depth */, 0, + gl[pixelFormat], gl[pixelType], null); + // Only upload the left half image to the right half texture. + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, 0); + gl.texSubImage3D(bindingTarget, 0, bitmap.width / 2, 0, 0, bitmap.width / 2, bitmap.height, 1, + gl[pixelFormat], gl[pixelType], bitmap); + tl = blackColor; + tr = srcTL; + bl = blackColor; + br = srcBL; + } else { + // Only upload the bottom middle quarter image + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, bitmap.height / 2); + gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, 0); + gl.texImage3D(bindingTarget, 0, gl[internalFormat], bitmap.width, bitmap.height / 2, 1 /* depth */, 0, + gl[pixelFormat], gl[pixelType], bitmap); + if (!flipY) { + tl = srcBL; + tr = srcBR; + bl = srcBL; + br = srcBR; + } else { + tl = srcTL; + tr = srcTR; + bl = srcTL; + br = srcTR; + } + } + } else { + if (useTexSubImage) { + // Initialize the texture to black first + gl.texImage2D(bindingTarget, 0, gl[internalFormat], bitmap.width, bitmap.height, 0, + gl[pixelFormat], gl[pixelType], null); + // Only upload the left half image to the right half texture. + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); + gl.texSubImage2D(bindingTarget, 0, bitmap.width / 2, 0, bitmap.width / 2, bitmap.height, + gl[pixelFormat], gl[pixelType], bitmap); + tl = blackColor; + tr = srcTL; + bl = blackColor; + br = srcBL; + } else { + // Only upload the right bottom image. + gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, bitmap.width / 2); + gl.pixelStorei(gl.UNPACK_SKIP_ROWS, bitmap.height / 2); + gl.texImage2D(bindingTarget, 0, gl[internalFormat], bitmap.width / 2, bitmap.height / 2, 0, + gl[pixelFormat], gl[pixelType], bitmap); + resetUnpackParams(gl); + if (!flipY) { + tl = srcBR; + tr = srcBR; + bl = srcBR; + br = srcBR; + } else { + tl = srcTR; + tr = srcTR; + bl = srcTR; + br = srcTR; + } + } + } + bufferedLogToConsole("Uploading texture completed"); + + var width = gl.canvas.width; + var halfWidth = Math.floor(width / 2); + var quaterWidth = Math.floor(halfWidth / 2); + var height = gl.canvas.height; + var halfHeight = Math.floor(height / 2); + var quaterHeight = Math.floor(halfHeight / 2); + + var top = flipY ? quaterHeight : (height - halfHeight + quaterHeight); + var bottom = flipY ? (height - halfHeight + quaterHeight) : quaterHeight; + + + var tolerance = 10; + // Draw the triangles + wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); + + // Check the top pixel and bottom pixel and make sure they have + // the right color. + // For right side, check pixels closer to left to avoid border in the video tests. + bufferedLogToConsole("Checking " + (flipY ? "top" : "bottom")); + wtu.checkCanvasRect(gl, quaterWidth, bottom, 2, 2, tl, "shouldBe " + tl, tolerance); + wtu.checkCanvasRect(gl, halfWidth + quaterWidth / 2, bottom, 2, 2, tr, "shouldBe " + tr, tolerance); + bufferedLogToConsole("Checking " + (flipY ? "bottom" : "top")); + wtu.checkCanvasRect(gl, quaterWidth, top, 2, 2, bl, "shouldBe " + bl, tolerance); + wtu.checkCanvasRect(gl, halfWidth + quaterWidth / 2, top, 2, 2, br, "shouldBe " + br, tolerance); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); +} + +function runTestOnBindingTargetImageBitmap(bindingTarget, program, bitmaps, optionsVal, + internalFormat, pixelFormat, pixelType, gl, tiu, wtu) +{ + var cases = [ + { sub: false, bitmap: bitmaps.noFlipYPremul, flipY: false, premultiply: true }, + { sub: true, bitmap: bitmaps.noFlipYPremul, flipY: false, premultiply: true }, + { sub: false, bitmap: bitmaps.noFlipYUnpremul, flipY: false, premultiply: false }, + { sub: true, bitmap: bitmaps.noFlipYUnpremul, flipY: false, premultiply: false }, + { sub: false, bitmap: bitmaps.flipYPremul, flipY: true, premultiply: true }, + { sub: true, bitmap: bitmaps.flipYPremul, flipY: true, premultiply: true }, + { sub: false, bitmap: bitmaps.flipYUnpremul, flipY: true, premultiply: false }, + { sub: true, bitmap: bitmaps.flipYUnpremul, flipY: true, premultiply: false }, + ]; + + for (var i in cases) { + runOneIterationImageBitmapTest(cases[i].sub, bindingTarget, program, cases[i].bitmap, + cases[i].flipY, cases[i].premultiply, optionsVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu); + } + + if (wtu.getDefault3DContextVersion() > 1 && + (bindingTarget == gl.TEXTURE_2D || bindingTarget == gl.TEXTURE_3D)) { + // SKip testing source sub region on TEXTURE_CUBE_MAP and TEXTURE_2D_ARRAY to save running time. + for (var i in cases) { + runOneIterationImageBitmapTestSubSource(cases[i].sub, bindingTarget, program, cases[i].bitmap, + cases[i].flipY, cases[i].premultiply, optionsVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu); + } + } +} + +function runImageBitmapTestInternal(bitmaps, alphaVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, is3D) +{ + var optionsVal = {alpha: alphaVal, is3D: is3D}; + var program; + if (is3D) { + program = tiu.setupTexturedQuadWith3D(gl, internalFormat); + runTestOnBindingTargetImageBitmap(gl.TEXTURE_3D, program, bitmaps, optionsVal, + internalFormat, pixelFormat, pixelType, gl, tiu, wtu); + } else { + program = tiu.setupTexturedQuad(gl, internalFormat); + runTestOnBindingTargetImageBitmap(gl.TEXTURE_2D, program, bitmaps, optionsVal, + internalFormat, pixelFormat, pixelType, gl, tiu, wtu); + } + + // cube map texture must be square + if (bitmaps.noFlipYPremul.width == bitmaps.noFlipYPremul.height) { + if (is3D) { + program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); + runTestOnBindingTargetImageBitmap(gl.TEXTURE_2D_ARRAY, program, bitmaps, optionsVal, + internalFormat, pixelFormat, pixelType, gl, tiu, wtu); + } else { + program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); + runTestOnBindingTargetImageBitmap(gl.TEXTURE_CUBE_MAP, program, bitmaps, optionsVal, + internalFormat, pixelFormat, pixelType, gl, tiu, wtu); + } + } +} + +function runImageBitmapTest(source, alphaVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, is3D) +{ + var bitmaps = []; + var p1 = createImageBitmap(source, {imageOrientation: "none", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.noFlipYPremul = imageBitmap }); + var p2 = createImageBitmap(source, {imageOrientation: "none", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.noFlipYUnpremul = imageBitmap }); + var p3 = createImageBitmap(source, {imageOrientation: "flipY", premultiplyAlpha: "premultiply"}).then(function(imageBitmap) { bitmaps.flipYPremul = imageBitmap }); + var p4 = createImageBitmap(source, {imageOrientation: "flipY", premultiplyAlpha: "none"}).then(function(imageBitmap) { bitmaps.flipYUnpremul = imageBitmap }); + Promise.all([p1, p2, p3, p4]).then(function() { + bufferedLogToConsole("All createImageBitmap promises are resolved"); + runImageBitmapTestInternal(bitmaps, alphaVal, internalFormat, pixelFormat, pixelType, gl, tiu, wtu, is3D); + }, function() { + // createImageBitmap with options could be rejected if it is not supported + finishTest(); + return; + }); +} diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/tex-input-validation.js b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-input-validation.js new file mode 100644 index 000000000..154dfbddf --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/tex-input-validation.js @@ -0,0 +1,580 @@ +/* +** Copyright (c) 2015 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. +*/ + +// This test relies on the surrounding web page defining a variable +// "contextVersion" which indicates what version of WebGL it's running +// on -- 1 for WebGL 1.0, 2 for WebGL 2.0, etc. + +"use strict"; +description("Validate tex functions input parameters"); + +var wtu = WebGLTestUtils; +var gl = null; +var tex = null; +var error = 0; + +shouldBeNonNull("gl = wtu.create3DContext(undefined, undefined, contextVersion)"); +shouldBeNonNull("tex = gl.createTexture()"); +gl.bindTexture(gl.TEXTURE_2D, tex); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +function enumToString(value) { + return wtu.glEnumToString(gl, value); +} + +function testTexParameter(testCase) { + var msg = "paramName: " + enumToString(testCase.pname); + error = testCase.expectedError; + gl.texParameteri(testCase.target, testCase.pname, testCase.param); + wtu.glErrorShouldBe(gl, error, msg); + gl.texParameterf(testCase.target, testCase.pname, testCase.param); + wtu.glErrorShouldBe(gl, error, msg); +} + +function testGetTexParameter(testCase) { + var msg = "paramName: " + enumToString(testCase.pname); + error = testCase.expectedError; + gl.getTexParameter(testCase.target, testCase.pname); + wtu.glErrorShouldBe(gl, error, msg); +} + +function testTexImage2D(testCase) { + var level = 0; + var width = 16; + var height = 16; + var msg = " internalFormat: " + enumToString(testCase.internalFormat) + + " target: " + enumToString(testCase.target) + + " format: " + enumToString(testCase.format) + + " type: " + enumToString(testCase.type) + + " border: " + testCase.border; + + gl.texImage2D(testCase.target, level, testCase.internalFormat, width, height, testCase.border, testCase.format, testCase.type, null); + error = testCase.expectedError; + wtu.glErrorShouldBe(gl, error, msg); +} + +function testTexSubImage2D(testCase) { + var level = 0; + var xoffset = 0; + var yoffset = 0; + var width = 16; + var height = 16; + var msg = " format: " + enumToString(testCase.format) + + " type: " + enumToString(testCase.type); + var array = new Uint8Array(width * height * 4); + + gl.texSubImage2D(testCase.target, level, xoffset, yoffset, width, height, testCase.format, testCase.type, array); + error = testCase.expectedError; + wtu.glErrorShouldBe(gl, error, msg); +} + +function testCopyTexImage2D(testCase) { + var level = 0; + var x = 0; + var y = 0; + var width = 16; + var height = 16; + var msg = " colorBufferFormat: " + enumToString(testCase.colorBufferFormat) + + " internalFormat: " + enumToString(testCase.internalFormat) + + " target: " + enumToString(testCase.target) + + " border: " + testCase.border; + + gl.renderbufferStorage(gl.RENDERBUFFER, testCase.colorBufferFormat, width, height); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); + + gl.copyTexImage2D(testCase.target, level, testCase.internalFormat, x, y, width, height, testCase.border); + error = testCase.expectedError; + wtu.glErrorShouldBe(gl, error, msg); +} + +function testCopyTexSubImage2D(testCase) { + var level = 0; + var x = 0; + var y = 0; + var width = 16; + var height = 16; + var xoffset = 0; + var yoffset = 0; + var border = 0; + var type = gl.UNSIGNED_BYTE; + var msg = " colorBufferFormat: " + enumToString(testCase.colorBufferFormat) + + " internalFormat: " + enumToString(testCase.internalFormat) + + " target: " + enumToString(testCase.target); + + gl.renderbufferStorage(gl.RENDERBUFFER, testCase.colorBufferFormat, width, height); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE"); + + gl.texImage2D(testCase.target, level, testCase.internalFormat, xoffset + width, yoffset + height, border, testCase.internalFormat, type, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + gl.copyTexSubImage2D(testCase.target, level, xoffset, yoffset, x, y, width, height); + error = testCase.expectedError; + wtu.glErrorShouldBe(gl, error, msg); +} + +function testCopyFromInternalFBO(testCase) { + var target = gl.TEXTURE_2D; + var level = 0; + var x = 0; + var y = 0; + var width = 16; + var height = 16; + var xoffset = 0; + var yoffset = 0; + var border = 0; + var type = gl.UNSIGNED_BYTE; + var msg = " colorBufferFormat: " + enumToString(testCase.contextAlpha ? gl.RGBA : gl.RGB) + + " internalFormat: " + enumToString(testCase.internalFormat); + + if (testCase.contextAlpha) { + gl = wtu.create3DContext(null, { alpha: true }, contextVersion); + } else { + gl = wtu.create3DContext(null, { alpha: false }, contextVersion); + } + shouldBeNonNull("gl"); + shouldBeNonNull("tex = gl.createTexture()"); + gl.bindTexture(target, tex); + if (testCase.subImage) { + gl.texImage2D(target, level, testCase.internalFormat, xoffset + width, yoffset + height, border, testCase.internalFormat, type, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + gl.copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); + } else { + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + gl.copyTexImage2D(target, level, testCase.internalFormat, x, y, width, height, border); + } + error = testCase.expectedError; + wtu.glErrorShouldBe(gl, error, msg); +} + +// Only for WebGL2.0. +function testTexImage3D(testCase) { + var level = 0; + var width = 16; + var height = 16; + var depth = 16; + var msg = " internalFormat: " + enumToString(testCase.internalFormat) + + " target: " + enumToString(testCase.target) + + " format: " + enumToString(testCase.format) + + " type: " + enumToString(testCase.type) + + " border: " + testCase.border; + + gl.texImage3D(testCase.target, level, testCase.internalFormat, width, height, depth, testCase.border, testCase.format, testCase.type, null); + error = testCase.expectedError; + wtu.glErrorShouldBe(gl, error, msg); +} + +function testTexSubImage3D(testCase) { + var level = 0; + var xoffset = 0; + var yoffset = 0; + var zoffset = 0; + var width = 16; + var height = 16; + var depth = 16; + var msg = " format: " + enumToString(testCase.format) + + " type: " + enumToString(testCase.type); + var array = new Uint8Array(width * height * depth * 4); + + gl.texSubImage3D(testCase.target, level, xoffset, yoffset, zoffset, width, height, depth, testCase.format, testCase.type, array); + error = testCase.expectedError; + wtu.glErrorShouldBe(gl, error, msg); +} + + +// Start checking. + +debug(""); +debug("Checking TexParameter: a set of inputs that are valid in GL but invalid in WebGL"); + +testCases = [ + { target: 0x0DE0, // GL_TEXTURE_1D + pname: gl.TEXTURE_WRAP_T, + param: gl.REPEAT, + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_2D, + pname: gl.TEXTURE_WRAP_T, + param: 0x2900, // GL_CLAMP + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_2D, + pname: gl.TEXTURE_WRAP_T, + param: gl.REPEAT, + expectedError: gl.NO_ERROR } +]; + +if (contextVersion < 2) { + testCases = testCases.concat([ + { target: gl.TEXTURE_2D, + pname: 0x813A, // GL_TEXTURE_MIN_LOD + param: 0, + expectedError: gl.INVALID_ENUM } + ]); +} else { + testCases = testCases.concat([ + { target: gl.TEXTURE_2D, + pname: 0x8E42, // GL_TEXTURE_SWIZZLE_R + param: 0x1903, // GL_RED + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_2D, + pname: 0x8072, // GL_TEXTURE_WRAP_R + param: 0x2900, // GL_CLAMP + expectedError: gl.INVALID_ENUM } + ]); +} + +for (var ii = 0; ii < testCases.length; ++ii) { + testTexParameter(testCases[ii]); +} + +debug(""); +debug("Checking GetTexParameter: a set of inputs that are valid in GL but invalid in WebGL"); + +testCases = [ + { target: 0x0DE0, // GL_TEXTURE_1D + pname: gl.TEXTURE_WRAP_T, + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_2D, + pname: gl.TEXTURE_WRAP_T, + expectedError: gl.NO_ERROR } +]; + +if (contextVersion < 2) { + testCases = testCases.concat([ + { target: gl.TEXTURE_2D, + pname: 0x813A, // GL_TEXTURE_MIN_LOD + expectedError: gl.INVALID_ENUM } + ]); +} else { + testCases = testCases.concat([ + { target: gl.TEXTURE_2D, + pname: 0x8E42, // GL_TEXTURE_SWIZZLE_R + expectedError: gl.INVALID_ENUM } + ]); +} + +for (var ii = 0; ii < testCases.length; ++ii) { + testGetTexParameter(testCases[ii]); +} + +debug(""); +debug("Checking TexImage2D: a set of inputs that are valid in GL but invalid in WebGL"); + +var testCases = [ + { target: 0x8064, // GL_PROXY_TEXTURE_2D + internalFormat: gl.RGBA, + border: 0, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_2D, + internalFormat: 0x1903, // GL_RED + border: 0, + format: 0x1903, // GL_RED + type: gl.UNSIGNED_BYTE, + expectedError: [gl.INVALID_ENUM, gl.INVALID_VALUE] }, + { target: gl.TEXTURE_2D, + internalFormat: gl.RGBA, + border: 1, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_VALUE }, + { target: gl.TEXTURE_2D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RGB, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_OPERATION }, + { target: gl.TEXTURE_2D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.NO_ERROR } +]; + +if (contextVersion < 2) { + testCases = testCases.concat([ + { target: gl.TEXTURE_2D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RGBA, + type: gl.BYTE, + expectedError: gl.INVALID_ENUM } + ]); +} else { + testCases = testCases.concat([ + { target: gl.TEXTURE_2D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RGBA, + type: gl.BYTE, + expectedError: gl.INVALID_OPERATION }, + { target: gl.TEXTURE_3D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_ENUM } + ]); +} + +for (var ii = 0; ii < testCases.length; ++ii) { + testTexImage2D(testCases[ii]); +} + +debug(""); +debug("Checking TexSubImage2D: a set of inputs that are valid in GL but invalid in WebGL"); + +testCases = [ + { target: gl.TEXTURE_2D, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.NO_ERROR } +]; + +if (contextVersion < 2) { + testCases = testCases.concat([ + { target: gl.TEXTURE_2D, + format: 0x1903, // GL_RED + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_2D, + format: gl.RGBA, + type: gl.BYTE, + expectedError: gl.INVALID_ENUM } + ]); +} else { + testCases = testCases.concat([ + { target: gl.TEXTURE_2D, + format: gl.RED, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_OPERATION }, + { target: gl.TEXTURE_2D, + format: gl.RGBA, + type: gl.BYTE, + expectedError: gl.INVALID_OPERATION }, + { target: gl.TEXTURE_3D, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_ENUM }, + ]); +} + +for (var ii = 0; ii < testCases.length; ++ii) { + testTexSubImage2D(testCases[ii]); +} + +debug(""); +debug("Checking CopyTexImage2D: a set of inputs that are valid in GL but invalid in WebGL"); + +var colorBuffer = null; +var fbo = null; + +shouldBeNonNull("fbo = gl.createFramebuffer()"); +gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); +shouldBeNonNull("colorBuffer = gl.createRenderbuffer()"); +gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); +gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +testCases = [ + { target: gl.TEXTURE_2D, + colorBufferFormat: gl.RGB565, + internalFormat: 0x8054, // GL_RGB16 + border: 0, + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_2D, + colorBufferFormat: gl.RGB565, + internalFormat: gl.RGBA, + border: 1, + expectedError: gl.INVALID_VALUE }, + { target: gl.TEXTURE_2D, + colorBufferFormat: gl.RGB565, + internalFormat: gl.RGBA, + border: 0, + expectedError: gl.INVALID_OPERATION }, + { target: gl.TEXTURE_2D, + colorBufferFormat: gl.RGB565, + internalFormat: gl.RGB, + border: 0, + expectedError: gl.NO_ERROR } +]; + +if (contextVersion > 1) { + testCases = testCases.concat([ + { target: gl.TEXTURE_3D, + colorBufferFormat: gl.RGB5_A1, + internalFormat: gl.RGBA, + border: 0, + expectedError: gl.INVALID_ENUM } + ]); +} + +for (var ii = 0; ii < testCases.length; ++ii) { + testCopyTexImage2D(testCases[ii]); +} + +debug(""); +debug("Checking CopyTexSubImage2D: a set of inputs that are valid in GL but invalid in WebGL"); + +testCases = [ + { target: gl.TEXTURE_2D, + colorBufferFormat: gl.RGB5_A1, + internalFormat: gl.RGBA, + expectedError: gl.NO_ERROR }, + { target: gl.TEXTURE_2D, + colorBufferFormat: gl.RGB565, + internalFormat: gl.RGBA, + expectedError: gl.INVALID_OPERATION } +]; + +for (var ii = 0; ii < testCases.length; ++ii) { + testCopyTexSubImage2D(testCases[ii]); +} + +debug(""); +debug("Checking CopyTex{Sub}Image2D: copy from WebGL internal framebuffer"); + +testCases = [ + { contextAlpha: true, + internalFormat: gl.RGBA, + subImage: false, + expectedError: gl.NO_ERROR }, + { contextAlpha: false, + internalFormat: gl.RGBA, + subImage: false, + expectedError: gl.INVALID_OPERATION }, + { contextAlpha: true, + internalFormat: gl.RGBA, + subImage: true, + expectedError: gl.NO_ERROR }, + { contextAlpha: false, + internalFormat: gl.RGBA, + subImage: true, + expectedError: gl.INVALID_OPERATION } +]; + +for (var ii = 0; ii < testCases.length; ++ii) { + testCopyFromInternalFBO(testCases[ii]); +} + +if (contextVersion > 1) { +// Create new texture for testing api of WebGL 2.0. +shouldBeNonNull("tex = gl.createTexture()"); +gl.bindTexture(gl.TEXTURE_3D, tex); +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug(""); +debug("Checking TexImage3D: a set of inputs that are valid in GL but invalid in WebGL"); + +var testCases = [ + { target: 0x8070, // GL_PROXY_TEXTURE_3D + internalFormat: gl.RGBA, + border: 0, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_3D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RGB, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_OPERATION }, + { target: gl.TEXTURE_3D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RGBA, + type: gl.BYTE, + expectedError: gl.INVALID_OPERATION}, + { target: gl.TEXTURE_3D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.NO_ERROR } +]; + +for (var ii = 0; ii < testCases.length; ++ii) { + testTexImage3D(testCases[ii]); +} + +debug(""); +debug("Checking TexImage3D: bad target, internalformats, formats, types"); + +var testCases = [ + { target: gl.TEXTURE_2D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_3D, + internalFormat: gl.RG, + border: 0, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_VALUE}, + { target: gl.TEXTURE_3D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RG8, + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_3D, + internalFormat: gl.RGBA, + border: 0, + format: gl.RGBA, + type: gl.INT, + expectedError: gl.INVALID_OPERATION}, +]; + +for (var ii = 0; ii < testCases.length; ++ii) { + testTexImage3D(testCases[ii]); +} + +debug(""); +debug("Checking TexSubImage3D: a set of inputs that are valid in GL but invalid in WebGL"); + +testCases = [ + { target: gl.TEXTURE_3D, + format: 0x80E0, // GL_BGR + type: gl.UNSIGNED_BYTE, + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_3D, + format: gl.RGBA, + type: 0x8032, // GL_UNSIGNED_BYTE_3_3_2 + expectedError: gl.INVALID_ENUM }, + { target: gl.TEXTURE_3D, + format: gl.RGBA, + type: gl.UNSIGNED_BYTE, + expectedError: gl.NO_ERROR } +]; + +for (var ii = 0; ii < testCases.length; ++ii) { + testTexSubImage3D(testCases[ii]); +} + +} + +var successfullyParsed = true; diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-test-cases.js b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-test-cases.js new file mode 100644 index 000000000..462eaae1b --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-test-cases.js @@ -0,0 +1,90 @@ +/* +** Copyright (c) 2013 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. +*/ + +// The "name" attribute is a concession to browsers which don't +// implement the "name" property on function objects. +var testCases = + [ {name: "Float32Array", + unsigned: false, + integral: false, + elementSizeInBytes: 4, + testValues: [ -500.5, 500.5 ], + expectedValues: [ -500.5, 500.5 ] + }, + {name: "Float64Array", + unsigned: false, + integral: false, + elementSizeInBytes: 8, + testValues: [ -500.5, 500.5 ], + expectedValues: [ -500.5, 500.5 ] + }, + {name: "Int8Array", + unsigned: false, + integral: true, + elementSizeInBytes: 1, + testValues: [ -128, 127, -129, 128 ], + expectedValues: [ -128, 127, 127, -128 ] + }, + {name: "Int16Array", + unsigned: false, + integral: true, + elementSizeInBytes: 2, + testValues: [ -32768, 32767, -32769, 32768 ], + expectedValues: [ -32768, 32767, 32767, -32768 ] + }, + {name: "Int32Array", + unsigned: false, + integral: true, + elementSizeInBytes: 4, + testValues: [ -2147483648, 2147483647, -2147483649, 2147483648 ], + expectedValues: [ -2147483648, 2147483647, 2147483647, -2147483648 ] + }, + {name: "Uint8Array", + unsigned: true, + integral: true, + elementSizeInBytes: 1, + testValues: [ 0, 255, -1, 256 ], + expectedValues: [ 0, 255, 255, 0 ] + }, + {name: "Uint8ClampedArray", + unsigned: true, + integral: true, + elementSizeInBytes: 1, + testValues: [ 0, 255, -1, 256 ], + expectedValues: [ 0, 255, 0, 255 ] + }, + {name: "Uint16Array", + unsigned: true, + integral: true, + elementSizeInBytes: 2, + testValues: [ 0, 65535, -1, 65536 ], + expectedValues: [ 0, 65535, 65535, 0 ] + }, + {name: "Uint32Array", + unsigned: true, + integral: true, + elementSizeInBytes: 4, + testValues: [ 0, 4294967295, -1, 4294967296 ], + expectedValues: [ 0, 4294967295, 4294967295, 0 ] + } + ]; diff --git a/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-worker.js b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-worker.js new file mode 100644 index 000000000..c68ee07c2 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/js/tests/typed-array-worker.js @@ -0,0 +1,89 @@ +/* +** Copyright (c) 2013 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. +*/ + +function constructTypedArray(type, data) { + if (type == 'Int8Array') { + return new Int8Array(data); + } else if (type == 'Uint8Array') { + return new Uint8Array(data); + } else if (type == 'Uint8ClampedArray') { + return new Uint8ClampedArray(data); + } else if (type == 'Int16Array') { + return new Int16Array(data); + } else if (type == 'Uint16Array') { + return new Uint16Array(data); + } else if (type == 'Int32Array') { + return new Int32Array(data); + } else if (type == 'Uint32Array') { + return new Uint32Array(data); + } else if (type == 'Float32Array') { + return new Float32Array(data); + } else if (type == 'Float64Array') { + return new Float64Array(data); + } +} + +function constructDataView(subType, elementSizeInBytes, data) { + var setter = "set" + subType; + var byteOffset = 0; + var buffer = new ArrayBuffer(elementSizeInBytes * data.length); + var dataView = new DataView(buffer); + for (var ii = 0; ii < data.length; ++ii) { + dataView[setter](byteOffset, data[ii]); + byteOffset += elementSizeInBytes; + } + return dataView; +} + +onmessage = function(event) { + var message = event.data; + if (message.command == 'copy' || + message.command == 'transfer' || + message.command == 'copyBuffer' || + message.command == 'transferBuffer') { + var view; + if (message.type != 'DataView') { + view = constructTypedArray(message.type, message.data); + } else { + view = constructDataView(message.subType, message.elementSizeInBytes, message.data); + } + var valueToSend; + if (message.command == 'copy' || + message.command == 'transfer') { + valueToSend = view; + } else { + valueToSend = view.buffer; + } + var transferablesToSend = undefined; + if (message.command == 'transfer' || + message.command == 'transferBuffer') { + transferablesToSend = [ view.buffer ]; + } + postMessage(valueToSend, transferablesToSend); + } else if (message.command == 'pong') { + postMessage(message.data, message.transferables); + } else if (message.command == 'ignore') { + } else { + postMessage('error: unknown message'); + } +}; |