tex-image-and-sub-image-2d-with-image-data.js (9606B)
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 imageData = null; 13 var blackColor = [0, 0, 0]; 14 var redColor = [255, 0, 0]; 15 var greenColor = [0, 255, 0]; 16 17 function init() 18 { 19 description('Verify texImage2D and texSubImage2D code paths taking ImageData (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); 20 21 // Set the default context version while still allowing the webglVersion URL query string to override it. 22 wtu.setDefault3DContextVersion(defaultContextVersion); 23 gl = wtu.create3DContext("example"); 24 25 if (!prologue(gl)) { 26 finishTest(); 27 return; 28 } 29 30 switch (gl[pixelFormat]) { 31 case gl.RED: 32 case gl.RED_INTEGER: 33 greenColor = [0, 0, 0]; 34 break; 35 case gl.LUMINANCE: 36 case gl.LUMINANCE_ALPHA: 37 redColor = [255, 255, 255]; 38 greenColor = [0, 0, 0]; 39 break; 40 case gl.ALPHA: 41 redColor = [0, 0, 0]; 42 greenColor = [0, 0, 0]; 43 break; 44 default: 45 break; 46 } 47 48 gl.clearColor(0,0,0,1); 49 gl.clearDepth(1); 50 gl.disable(gl.BLEND); 51 52 var canvas2d = document.getElementById("texcanvas"); 53 var context2d = canvas2d.getContext("2d"); 54 imageData = context2d.createImageData(2, 2); 55 var data = imageData.data; 56 data[0] = 255; 57 data[1] = 0; 58 data[2] = 0; 59 data[3] = 255; 60 data[4] = 255; 61 data[5] = 0; 62 data[6] = 0; 63 data[7] = 0; 64 data[8] = 0; 65 data[9] = 255; 66 data[10] = 0; 67 data[11] = 255; 68 data[12] = 0; 69 data[13] = 255; 70 data[14] = 0; 71 data[15] = 0; 72 73 runTest(); 74 } 75 76 function runOneIteration(useTexSubImage2D, flipY, premultiplyAlpha, 77 sourceSubRectangle, expected, 78 bindingTarget, program) 79 { 80 sourceSubRectangleString = ''; 81 if (sourceSubRectangle) { 82 sourceSubRectangleString = ', sourceSubRectangle=' + sourceSubRectangle; 83 } 84 debug(''); 85 debug('Testing ' + (useTexSubImage2D ? 'texSubImage2D' : 'texImage2D') + 86 ' with flipY=' + flipY + ' and premultiplyAlpha=' + premultiplyAlpha + 87 ', bindingTarget=' + (bindingTarget == gl.TEXTURE_2D ? 'TEXTURE_2D' : 'TEXTURE_CUBE_MAP') + 88 sourceSubRectangleString); 89 90 var loc; 91 if (bindingTarget == gl.TEXTURE_CUBE_MAP) { 92 loc = gl.getUniformLocation(program, "face"); 93 } 94 95 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 96 // Enable writes to the RGBA channels 97 gl.colorMask(1, 1, 1, 0); 98 var texture = gl.createTexture(); 99 // Bind the texture to texture unit 0 100 gl.bindTexture(bindingTarget, texture); 101 // Set up texture parameters 102 gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 103 gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 104 // Set up pixel store parameters 105 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); 106 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha); 107 var targets = [gl.TEXTURE_2D]; 108 if (bindingTarget == gl.TEXTURE_CUBE_MAP) { 109 targets = [gl.TEXTURE_CUBE_MAP_POSITIVE_X, 110 gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 111 gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 112 gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 113 gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 114 gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]; 115 } 116 // Handle the source sub-rectangle if specified (WebGL 2.0 only) 117 if (sourceSubRectangle) { 118 gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); 119 gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); 120 } 121 // Upload the image into the texture 122 for (var tt = 0; tt < targets.length; ++tt) { 123 if (sourceSubRectangle) { 124 if (useTexSubImage2D) { 125 // Initialize the texture to black first 126 gl.texImage2D(targets[tt], 0, gl[internalFormat], 127 sourceSubRectangle[2], sourceSubRectangle[3], 0, 128 gl[pixelFormat], gl[pixelType], null); 129 gl.texSubImage2D(targets[tt], 0, 0, 0, 130 sourceSubRectangle[2], sourceSubRectangle[3], 131 gl[pixelFormat], gl[pixelType], imageData); 132 } else { 133 gl.texImage2D(targets[tt], 0, gl[internalFormat], 134 sourceSubRectangle[2], sourceSubRectangle[3], 0, 135 gl[pixelFormat], gl[pixelType], imageData); 136 } 137 } else { 138 if (useTexSubImage2D) { 139 // Initialize the texture to black first 140 gl.texImage2D(targets[tt], 0, gl[internalFormat], imageData.width, imageData.height, 0, 141 gl[pixelFormat], gl[pixelType], null); 142 gl.texSubImage2D(targets[tt], 0, 0, 0, gl[pixelFormat], gl[pixelType], imageData); 143 } else { 144 gl.texImage2D(targets[tt], 0, gl[internalFormat], gl[pixelFormat], gl[pixelType], imageData); 145 } 146 } 147 } 148 149 if (sourceSubRectangle) { 150 gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); 151 gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); 152 } 153 154 var width = gl.canvas.width; 155 var halfWidth = Math.floor(width / 2); 156 var height = gl.canvas.height; 157 var halfHeight = Math.floor(height / 2); 158 159 var top = 0; 160 var bottom = height - halfHeight; 161 var left = 0; 162 var right = width - halfWidth; 163 164 var tl, tr, bl, br; 165 if (expected.length == 1) { 166 tl = tr = bl = br = expected[0]; 167 } else { 168 tl = expected[0]; 169 tr = expected[1]; 170 bl = expected[2]; 171 br = expected[3]; 172 } 173 174 for (var tt = 0; tt < targets.length; ++tt) { 175 if (bindingTarget == gl.TEXTURE_CUBE_MAP) { 176 gl.uniform1i(loc, targets[tt]); 177 } 178 // Draw the triangles 179 wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); 180 181 // Check the top pixel and bottom pixel and make sure they have 182 // the right color. 183 wtu.checkCanvasRect(gl, left, top, halfWidth, halfHeight, tl, "shouldBe " + tl); 184 wtu.checkCanvasRect(gl, right, top, halfWidth, halfHeight, tr, "shouldBe " + tr); 185 wtu.checkCanvasRect(gl, left, bottom, halfWidth, halfHeight, bl, "shouldBe " + bl); 186 wtu.checkCanvasRect(gl, right, bottom, halfWidth, halfHeight, br, "shouldBe " + br); 187 } 188 } 189 190 function runTest() 191 { 192 var program = tiu.setupTexturedQuad(gl, internalFormat); 193 runTestOnBindingTarget(gl.TEXTURE_2D, program); 194 program = tiu.setupTexturedQuadWithCubeMap(gl, internalFormat); 195 runTestOnBindingTarget(gl.TEXTURE_CUBE_MAP, program); 196 197 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); 198 finishTest(); 199 } 200 201 function runTestOnBindingTarget(bindingTarget, program) { 202 var k = blackColor; 203 var r = redColor; 204 var g = greenColor; 205 var cases = [ 206 { expected: [r, r, g, g], flipY: false, premultiplyAlpha: false, sub: false }, 207 { expected: [r, r, g, g], flipY: false, premultiplyAlpha: false, sub: true }, 208 { expected: [r, k, g, k], flipY: false, premultiplyAlpha: true, sub: false }, 209 { expected: [r, k, g, k], flipY: false, premultiplyAlpha: true, sub: true }, 210 { expected: [g, g, r, r], flipY: true, premultiplyAlpha: false, sub: false }, 211 { expected: [g, g, r, r], flipY: true, premultiplyAlpha: false, sub: true }, 212 { expected: [g, k, r, k], flipY: true, premultiplyAlpha: true, sub: false }, 213 { expected: [g, k, r, k], flipY: true, premultiplyAlpha: true, sub: true }, 214 ]; 215 216 if (wtu.getDefault3DContextVersion() > 1) { 217 var morecases = []; 218 // Make 2 copies of the original case: top left and bottom right 1x1 rectangles 219 for (var i = 0; i < cases.length; i++) { 220 for (var subX = 0; subX <= 1; subX++) { 221 var subY = subX == 0 ? 1 : 0; 222 // shallow-copy cases[i] into newcase 223 var newcase = Object.assign({}, cases[i]); 224 newcase.expected = [cases[i].expected[subY * 2 + subX]]; 225 newcase.sourceSubRectangle = [subX, subY, 1, 1]; 226 morecases.push(newcase); 227 } 228 } 229 cases = cases.concat(morecases); 230 } 231 232 for (var i in cases) { 233 runOneIteration(cases[i].sub, cases[i].flipY, cases[i].premultiplyAlpha, 234 cases[i].sourceSubRectangle, cases[i].expected, 235 bindingTarget, program); 236 } 237 } 238 239 return init; 240 }