tex-image-and-sub-image-2d-with-image.js (10449B)
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 imgCanvas; 13 var redColor = [255, 0, 0]; 14 var greenColor = [0, 255, 0]; 15 16 function init() 17 { 18 description('Verify texImage2D and texSubImage2D code paths taking image 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 greenColor = [0, 0, 0]; 33 break; 34 35 case gl.LUMINANCE: 36 case gl.LUMINANCE_ALPHA: 37 redColor = [255, 255, 255]; 38 greenColor = [0, 0, 0]; 39 break; 40 41 case gl.ALPHA: 42 redColor = [0, 0, 0]; 43 greenColor = [0, 0, 0]; 44 break; 45 46 default: 47 break; 48 } 49 50 gl.clearColor(0,0,0,1); 51 gl.clearDepth(1); 52 53 wtu.loadTexture(gl, resourcePath + "red-green.png", runTest); 54 } 55 56 function runOneIteration(image, useTexSubImage2D, flipY, topColor, bottomColor, 57 sourceSubRectangle, bindingTarget, program) 58 { 59 sourceSubRectangleString = ''; 60 if (sourceSubRectangle) { 61 sourceSubRectangleString = ' sourceSubRectangle=' + sourceSubRectangle; 62 } 63 debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + 64 ' with ' + image.width + 'x' + image.height + ' flipY=' + flipY + ' bindingTarget=' + 65 (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') + 66 sourceSubRectangleString); 67 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 68 // Disable any writes to the alpha channel 69 gl.colorMask(1, 1, 1, 0); 70 var texture = gl.createTexture(); 71 // Bind the texture to texture unit 0 72 gl.bindTexture(bindingTarget, texture); 73 // Set up texture parameters 74 gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 75 gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 76 // Set up pixel store parameters 77 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); 78 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); 79 wtu.failIfGLError(gl, 'gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);'); 80 var targets = [gl.TEXTURE_2D]; 81 if (bindingTarget == gl.TEXTURE_CUBE_MAP) { 82 targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, 83 gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 84 gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 85 gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 86 gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 87 gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; 88 } 89 // Handle the source sub-rectangle if specified (WebGL 2.0 only) 90 if (sourceSubRectangle) { 91 gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); 92 gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); 93 } 94 // Upload the image into the texture 95 for (var tt = 0; tt < targets.length; ++tt) { 96 if (sourceSubRectangle) { 97 if (useTexSubImage2D) { 98 // Initialize the texture to black first 99 gl.texImage2D(targets[tt], 0, gl[internalFormat], 100 sourceSubRectangle[2], sourceSubRectangle[3], 0, 101 gl[pixelFormat], gl[pixelType], null); 102 gl.texSubImage2D(targets[tt], 0, 0, 0, 103 sourceSubRectangle[2], sourceSubRectangle[3], 104 gl[pixelFormat], gl[pixelType], image); 105 } else { 106 gl.texImage2D(targets[tt], 0, gl[internalFormat], 107 sourceSubRectangle[2], sourceSubRectangle[3], 0, 108 gl[pixelFormat], gl[pixelType], image); 109 } 110 } else { 111 if (useTexSubImage2D) { 112 // Initialize the texture to black first 113 gl.texImage2D(targets[tt], 0, gl[internalFormat], image.width, image.height, 0, 114 gl[pixelFormat], gl[pixelType], null); 115 gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], image); 116 } else { 117 gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], image); 118 } 119 } 120 } 121 122 if (sourceSubRectangle) { 123 gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); 124 gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); 125 } 126 127 var loc; 128 if (bindingTarget == gl.TEXTURE_CUBE_MAP) { 129 loc = gl.getUniformLocation(program, "face"); 130 } 131 132 for (var tt = 0; tt < targets.length; ++tt) { 133 if (bindingTarget == gl.TEXTURE_CUBE_MAP) { 134 gl.uniform1i(loc, targets[tt]); 135 } 136 137 // Draw the triangles 138 wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); 139 // Check a few pixels near the top and bottom and make sure they have 140 // the right color. 141 debug("Checking lower left corner"); 142 wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor, 143 "shouldBe " + bottomColor); 144 debug("Checking upper left corner"); 145 wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor, 146 "shouldBe " + topColor); 147 } 148 } 149 150 function runTestOnImage(image) { 151 var cases = [ 152 { sub: false, flipY: true, topColor: redColor, bottomColor: greenColor }, 153 { sub: false, flipY: false, topColor: greenColor, bottomColor: redColor }, 154 { sub: true, flipY: true, topColor: redColor, bottomColor: greenColor }, 155 { sub: true, flipY: false, topColor: greenColor, bottomColor: redColor }, 156 ]; 157 158 159 if (wtu.getDefault3DContextVersion() > 1) { 160 cases = cases.concat([ 161 { sub: false, flipY: false, topColor: redColor, bottomColor: redColor, 162 sourceSubRectangle: [0, 0, 1, 1] }, 163 { sub: false, flipY: true, topColor: greenColor, bottomColor: greenColor, 164 sourceSubRectangle: [0, 0, 1, 1] }, 165 { sub: false, flipY: false, topColor: greenColor, bottomColor: greenColor, 166 sourceSubRectangle: [0, 1, 1, 1] }, 167 { sub: false, flipY: true, topColor: redColor, bottomColor: redColor, 168 sourceSubRectangle: [0, 1, 1, 1] }, 169 { sub: true, flipY: false, topColor: redColor, bottomColor: redColor, 170 sourceSubRectangle: [0, 0, 1, 1] }, 171 { sub: true, flipY: true, topColor: greenColor, bottomColor: greenColor, 172 sourceSubRectangle: [0, 0, 1, 1] }, 173 { sub: true, flipY: false, topColor: greenColor, bottomColor: greenColor, 174 sourceSubRectangle: [0, 1, 1, 1] }, 175 { sub: true, flipY: true, topColor: redColor, bottomColor: redColor, 176 sourceSubRectangle: [0, 1, 1, 1] }, 177 ]); 178 } 179 180 var program = tiu.setupTexturedQuad(gl, internalFormat); 181 for (var i in cases) { 182 runOneIteration(image, cases[i].sub, cases[i].flipY, 183 cases[i].topColor, cases[i].bottomColor, 184 cases[i].sourceSubRectangle, 185 gl.TEXTURE_2D, program); 186 } 187 // cube map texture must be square. 188 if (image.width != image.height) 189 return; 190 // Skip sub-rectangle tests for cube map textures for the moment. 191 program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); 192 for (var i in cases) { 193 if (!cases[i].sourceSubRectangle) { 194 runOneIteration(image, cases[i].sub, cases[i].flipY, 195 cases[i].topColor, cases[i].bottomColor, 196 undefined, 197 gl.TEXTURE_CUBE_MAP, program); 198 } 199 } 200 } 201 202 function runTest(image) 203 { 204 runTestOnImage(image); 205 206 imgCanvas = document.createElement("canvas"); 207 imgCanvas.width = 2; 208 imgCanvas.height = 2; 209 var imgCtx = imgCanvas.getContext("2d"); 210 var imgData = imgCtx.createImageData(2, 2); 211 imgData.data[0] = redColor[0]; 212 imgData.data[1] = redColor[1]; 213 imgData.data[2] = redColor[2]; 214 imgData.data[3] = 255; 215 imgData.data[4] = redColor[0]; 216 imgData.data[5] = redColor[1]; 217 imgData.data[6] = redColor[2]; 218 imgData.data[7] = 255; 219 imgData.data[8] = greenColor[0]; 220 imgData.data[9] = greenColor[1]; 221 imgData.data[10] = greenColor[2]; 222 imgData.data[11] = 255; 223 imgData.data[12] = greenColor[0]; 224 imgData.data[13] = greenColor[1]; 225 imgData.data[14] = greenColor[2]; 226 imgData.data[15] = 255; 227 imgCtx.putImageData(imgData, 0, 0); 228 229 // apparently Image is different than <img>. 230 var newImage = new Image(); 231 newImage.onload = function() { 232 runTest2(newImage); 233 }; 234 newImage.onerror = function() { 235 testFailed("Creating image from canvas failed. Image src: " + this.src); 236 finishTest(); 237 }; 238 newImage.src = imgCanvas.toDataURL(); 239 } 240 241 function runTest2(image) { 242 runTestOnImage(image); 243 244 wtu.makeImageFromCanvas(imgCanvas, function() { 245 runTest3(this); 246 }); 247 } 248 249 function runTest3(image) { 250 runTestOnImage(image); 251 252 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); 253 finishTest(); 254 } 255 256 return init; 257 }