tex-image-and-sub-image-3d-with-canvas.js (8657B)
1 /* 2 Copyright (c) 2019 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 */ 6 7 function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { 8 var wtu = WebGLTestUtils; 9 var tiu = TexImageUtils; 10 var gl = null; 11 var successfullyParsed = false; 12 var whiteColor = [255, 255, 255, 255]; 13 var redColor = [255, 0, 0]; 14 var greenColor = [0, 255, 0]; 15 16 function init() 17 { 18 description('Verify texImage3D and texSubImage3D code paths taking canvas elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); 19 20 // Set the default context version while still allowing the webglVersion URL query string to override it. 21 wtu.setDefault3DContextVersion(defaultContextVersion); 22 gl = wtu.create3DContext("example"); 23 24 if (!prologue(gl)) { 25 finishTest(); 26 return; 27 } 28 29 switch (gl[pixelFormat]) { 30 case gl.RED: 31 case gl.RED_INTEGER: 32 whiteColor = [255, 0, 0, 255]; 33 greenColor = [0, 0, 0]; 34 break; 35 case gl.RG: 36 case gl.RG_INTEGER: 37 whiteColor = [255, 255, 0, 255]; 38 break; 39 default: 40 break; 41 } 42 43 gl.clearColor(0,0,0,1); 44 gl.clearDepth(1); 45 46 runTest(); 47 } 48 49 function setCanvasToRedGreen(ctx) { 50 var width = ctx.canvas.width; 51 var height = ctx.canvas.height; 52 var halfHeight = Math.floor(height / 2); 53 ctx.fillStyle = "#ff0000"; 54 ctx.fillRect(0, 0, width, halfHeight); 55 ctx.fillStyle = "#00ff00"; 56 ctx.fillRect(0, halfHeight, width, height - halfHeight); 57 } 58 59 function drawTextInCanvas(ctx, bindingTarget) { 60 var width = ctx.canvas.width; 61 var height = ctx.canvas.height; 62 ctx.fillStyle = "#ffffff"; 63 ctx.fillRect(0, 0, width, height); 64 ctx.font = '20pt Arial'; 65 ctx.fillStyle = 'black'; 66 ctx.textAlign = "center"; 67 ctx.textBaseline = "middle"; 68 ctx.fillText("1234567890", width / 2, height / 4); 69 } 70 71 function setCanvasTo257x257(ctx, bindingTarget) { 72 ctx.canvas.width = 257; 73 ctx.canvas.height = 257; 74 setCanvasToRedGreen(ctx); 75 } 76 77 function setCanvasToMin(ctx, bindingTarget) { 78 if (bindingTarget == gl.TEXTURE_CUBE_MAP) { 79 // cube map texture must be square. 80 ctx.canvas.width = 2; 81 } else { 82 ctx.canvas.width = 1; 83 } 84 ctx.canvas.height = 2; 85 setCanvasToRedGreen(ctx); 86 } 87 88 function runOneIteration(canvas, flipY, program, bindingTarget, opt_texture, opt_fontTest) 89 { 90 var objType = 'canvas'; 91 if (canvas.transferToImageBitmap) 92 objType = 'OffscreenCanvas'; 93 debug('Testing ' + ' with flipY=' + flipY + ' bindingTarget=' + (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') + 94 ' source object: ' + objType + ' canvas size: ' + canvas.width + 'x' + canvas.height + (opt_fontTest ? " with fonts" : " with red-green")); 95 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 96 if (!opt_texture) { 97 var texture = gl.createTexture(); 98 // Bind the texture to texture unit 0 99 gl.bindTexture(bindingTarget, texture); 100 // Set up texture parameters 101 gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 102 gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 103 gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); 104 gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 105 gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 106 } else { 107 var texture = opt_texture; 108 } 109 // Set up pixel store parameters 110 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); 111 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); 112 wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);'); 113 // Initialize the texture to black first 114 gl.texImage3D(bindingTarget, 0, gl[internalFormat], canvas.width, canvas.height, 1 /* depth */, 0, 115 gl[pixelFormat], gl[pixelType], null); 116 gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, canvas.width, canvas.height, 1 /* depth */, 117 gl[pixelFormat], gl[pixelType], canvas); 118 119 var width = gl.canvas.width; 120 var height = gl.canvas.height; 121 var halfHeight = Math.floor(height / 2); 122 var top = flipY ? 0 : (height - halfHeight); 123 var bottom = flipY ? (height - halfHeight) : 0; 124 125 // Draw the triangles 126 wtu.clearAndDrawUnitQuad(gl, [0, 255, 0, 255]); 127 128 if (opt_fontTest) { 129 // check half is a solid color. 130 wtu.checkCanvasRect( 131 gl, 0, top, width, halfHeight, 132 whiteColor, 133 "should be white"); 134 // check other half is not a solid color. 135 wtu.checkCanvasRectColor( 136 gl, 0, bottom, width, halfHeight, 137 whiteColor, 0, 138 function() { 139 testFailed("font missing"); 140 }, 141 function() { 142 testPassed("font renderered"); 143 }, 144 debug); 145 } else { 146 // Check the top and bottom halves and make sure they have the right color. 147 debug("Checking " + (flipY ? "top" : "bottom")); 148 wtu.checkCanvasRect(gl, 0, bottom, width, halfHeight, redColor, 149 "shouldBe " + redColor); 150 debug("Checking " + (flipY ? "bottom" : "top")); 151 wtu.checkCanvasRect(gl, 0, top, width, halfHeight, greenColor, 152 "shouldBe " + greenColor); 153 } 154 155 return texture; 156 } 157 158 function runTest(canvas) 159 { 160 var canvas = document.createElement('canvas'); 161 162 var cases = [ 163 { canvas: canvas, flipY: true, font: false, init: setCanvasToMin }, 164 { canvas: canvas, flipY: false, font: false }, 165 { canvas: canvas, flipY: true, font: false, init: setCanvasTo257x257 }, 166 { canvas: canvas, flipY: false, font: false }, 167 { canvas: canvas, flipY: true, font: true, init: drawTextInCanvas }, 168 { canvas: canvas, flipY: false, font: true }, 169 ]; 170 171 if (window.OffscreenCanvas) { 172 var offscreenCanvas = new OffscreenCanvas(1, 1); 173 cases = cases.concat([ 174 { canvas: offscreenCanvas, flipY: true, font: false, init: setCanvasToMin }, 175 { canvas: offscreenCanvas, flipY: false, font: false }, 176 ]); 177 } 178 179 function runTexImageTest(bindingTarget) { 180 var program; 181 if (bindingTarget == gl.TEXTURE_3D) { 182 program = tiu.setupTexturedQuadWith3D(gl, internalFormat); 183 } else { // TEXTURE_2D_ARRAY 184 program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); 185 } 186 187 return new Promise(function(resolve, reject) { 188 var count = 4; 189 var caseNdx = 0; 190 var texture = undefined; 191 function runNextTest() { 192 var c = cases[caseNdx]; 193 if (c.init) { 194 c.init(c.canvas.getContext('2d'), bindingTarget); 195 } 196 texture = runOneIteration(c.canvas, c.flipY, program, bindingTarget, texture, c.font); 197 // for the first 2 iterations always make a new texture. 198 if (count < 2) { 199 gl.deleteTexture(texture); 200 texture = undefined; 201 } 202 ++caseNdx; 203 if (caseNdx == cases.length) { 204 caseNdx = 0; 205 --count; 206 if (!count) { 207 resolve("SUCCESS"); 208 return; 209 } 210 } 211 wtu.waitForComposite(runNextTest); 212 } 213 runNextTest(); 214 }); 215 } 216 217 runTexImageTest(gl.TEXTURE_3D).then(function(val) { 218 runTexImageTest(gl.TEXTURE_2D_ARRAY).then(function(val) { 219 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); 220 finishTest(); 221 }); 222 }); 223 } 224 225 return init; 226 }