tex-image-and-sub-image-3d-with-video.js (10592B)
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 // This block needs to be outside the onload handler in order for this 8 // test to run reliably in WebKit's test harness (at least the 9 // Chromium port). https://bugs.webkit.org/show_bug.cgi?id=87448 10 initTestingHarness(); 11 12 var old = debug; 13 var debug = function(msg) { 14 bufferedLogToConsole(msg); 15 old(msg); 16 }; 17 18 function generateTest(internalFormat, pixelFormat, pixelType, prologue, resourcePath, defaultContextVersion) { 19 var wtu = WebGLTestUtils; 20 var tiu = TexImageUtils; 21 var gl = null; 22 var successfullyParsed = false; 23 var redColor = [255, 0, 0]; 24 var greenColor = [0, 255, 0]; 25 26 // Test each format separately because many browsers implement each 27 // differently. Some might be GPU accelerated, some might not. Etc... 28 var videos = [ 29 { src: resourcePath + "red-green.mp4" , type: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', }, 30 { src: resourcePath + "red-green.bt601.vp9.webm", type: 'video/webm; codecs="vp9"', }, 31 { src: resourcePath + "red-green.webmvp8.webm", type: 'video/webm; codecs="vp8, vorbis"', }, 32 ]; 33 34 function init() 35 { 36 description('Verify texImage3D and texSubImage3D code paths taking video elements (' + internalFormat + '/' + pixelFormat + '/' + pixelType + ')'); 37 38 // Set the default context version while still allowing the webglVersion URL query string to override it. 39 wtu.setDefault3DContextVersion(defaultContextVersion); 40 gl = wtu.create3DContext("example"); 41 42 if (!prologue(gl)) { 43 finishTest(); 44 return; 45 } 46 47 switch (gl[pixelFormat]) { 48 case gl.RED: 49 case gl.RED_INTEGER: 50 greenColor = [0, 0, 0]; 51 break; 52 default: 53 break; 54 } 55 56 gl.clearColor(0,0,0,1); 57 gl.clearDepth(1); 58 59 runTest(); 60 } 61 62 function runOneIteration(videoElement, flipY, useTexSubImage3D, topColor, bottomColor, program, bindingTarget, 63 depth, sourceSubRectangle, unpackImageHeight, rTextureCoord) 64 { 65 debug('Testing ' + 66 (useTexSubImage3D ? "texSubImage3D" : "texImage3D") + 67 ' with flipY=' + flipY + ' bindingTarget=' + 68 (bindingTarget == gl.TEXTURE_3D ? 'TEXTURE_3D' : 'TEXTURE_2D_ARRAY') + 69 (sourceSubRectangle ? ', sourceSubRectangle=' + sourceSubRectangle : '') + 70 (unpackImageHeight ? ', unpackImageHeight=' + unpackImageHeight : '') + 71 ', depth=' + depth + 72 ', rTextureCoord=' + rTextureCoord); 73 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 74 // Disable any writes to the alpha channel 75 gl.colorMask(1, 1, 1, 0); 76 var texture = gl.createTexture(); 77 // Bind the texture to texture unit 0 78 gl.bindTexture(bindingTarget, texture); 79 // Set up texture parameters 80 gl.texParameteri(bindingTarget, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 81 gl.texParameteri(bindingTarget, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 82 gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); 83 gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 84 gl.texParameteri(bindingTarget, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 85 // Set up pixel store parameters 86 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY); 87 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); 88 gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); 89 var uploadWidth = videoElement.width; 90 var uploadHeight = videoElement.height; 91 if (sourceSubRectangle) { 92 gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, sourceSubRectangle[0]); 93 gl.pixelStorei(gl.UNPACK_SKIP_ROWS, sourceSubRectangle[1]); 94 uploadWidth = sourceSubRectangle[2]; 95 uploadHeight = sourceSubRectangle[3]; 96 } 97 if (unpackImageHeight) { 98 gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight); 99 } 100 // Upload the videoElement into the texture 101 if (useTexSubImage3D) { 102 // Initialize the texture to black first 103 gl.texImage3D(bindingTarget, 0, gl[internalFormat], 104 uploadWidth, uploadHeight, depth, 0, 105 gl[pixelFormat], gl[pixelType], null); 106 gl.texSubImage3D(bindingTarget, 0, 0, 0, 0, 107 uploadWidth, uploadHeight, depth, 108 gl[pixelFormat], gl[pixelType], videoElement); 109 } else { 110 gl.texImage3D(bindingTarget, 0, gl[internalFormat], 111 uploadWidth, uploadHeight, depth, 0, 112 gl[pixelFormat], gl[pixelType], videoElement); 113 } 114 gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, 0); 115 gl.pixelStorei(gl.UNPACK_SKIP_ROWS, 0); 116 gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, 0); 117 118 var c = document.createElement("canvas"); 119 c.width = 16; 120 c.height = 16; 121 c.style.border = "1px solid black"; 122 var ctx = c.getContext("2d"); 123 ctx.drawImage(videoElement, 0, 0, 16, 16); 124 document.body.appendChild(c); 125 126 var rCoordLocation = gl.getUniformLocation(program, 'uRCoord'); 127 if (!rCoordLocation) { 128 testFailed('Shader incorrectly set up; couldn\'t find uRCoord uniform'); 129 return; 130 } 131 gl.uniform1f(rCoordLocation, rTextureCoord); 132 133 // Draw the triangles 134 wtu.clearAndDrawUnitQuad(gl, [0, 0, 0, 255]); 135 // Check a few pixels near the top and bottom and make sure they have 136 // the right color. 137 const tolerance = 6; 138 debug("Checking lower left corner"); 139 wtu.checkCanvasRect(gl, 4, 4, 2, 2, bottomColor, 140 "shouldBe " + bottomColor, tolerance); 141 debug("Checking upper left corner"); 142 wtu.checkCanvasRect(gl, 4, gl.canvas.height - 8, 2, 2, topColor, 143 "shouldBe " + topColor, tolerance); 144 } 145 146 function runTest(videoElement) 147 { 148 var cases = [ 149 // No UNPACK_IMAGE_HEIGHT specified. 150 { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 5, rTextureCoord: 0, 151 topColor: redColor, bottomColor: redColor }, 152 // Note that an rTextureCoord of 4.0 satisfies the need to 153 // have it be >= 1.0 for the TEXTURE_3D case, and also its 154 // use as an index in the TEXTURE_2D_ARRAY case. 155 { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 5, rTextureCoord: 4, 156 topColor: greenColor, bottomColor: greenColor }, 157 { flipY: false, sourceSubRectangle: [24, 48, 32, 32], depth: 1, rTextureCoord: 0, 158 topColor: greenColor, bottomColor: redColor }, 159 { flipY: true, sourceSubRectangle: [24, 48, 32, 32], depth: 1, rTextureCoord: 0, 160 topColor: redColor, bottomColor: greenColor }, 161 162 // Use UNPACK_IMAGE_HEIGHT to skip some pixels. 163 { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 2, unpackImageHeight: 64, rTextureCoord: 0, 164 topColor: redColor, bottomColor: redColor }, 165 { flipY: false, sourceSubRectangle: [32, 16, 16, 16], depth: 2, unpackImageHeight: 64, rTextureCoord: 1, 166 topColor: greenColor, bottomColor: greenColor }, 167 ]; 168 169 function runTexImageTest(bindingTarget) { 170 var program; 171 if (bindingTarget == gl.TEXTURE_3D) { 172 program = tiu.setupTexturedQuadWith3D(gl, internalFormat); 173 } else { 174 program = tiu.setupTexturedQuadWith2DArray(gl, internalFormat); 175 } 176 177 return new Promise(function(resolve, reject) { 178 var videoNdx = 0; 179 var video; 180 function runNextVideo() { 181 if (video) { 182 video.pause(); 183 } 184 185 if (videoNdx == videos.length) { 186 resolve("SUCCESS"); 187 return; 188 } 189 190 var info = videos[videoNdx++]; 191 debug(""); 192 debug("testing: " + info.type); 193 video = document.createElement("video"); 194 video.muted = true; 195 var canPlay = true; 196 if (!video.canPlayType) { 197 testFailed("video.canPlayType required method missing"); 198 runNextVideo(); 199 return; 200 } 201 202 if(!video.canPlayType(info.type).replace(/no/, '')) { 203 debug(info.type + " unsupported"); 204 runNextVideo(); 205 return; 206 }; 207 208 document.body.appendChild(video); 209 video.type = info.type; 210 video.src = info.src; 211 wtu.startPlayingAndWaitForVideo(video, runTest); 212 } 213 function runTest() { 214 for (var i in cases) { 215 runOneIteration(video, cases[i].flipY, false, 216 cases[i].topColor, cases[i].bottomColor, 217 program, bindingTarget, cases[i].depth, 218 cases[i].sourceSubRectangle, 219 cases[i].unpackImageHeight, 220 cases[i].rTextureCoord); 221 runOneIteration(video, cases[i].flipY, true, 222 cases[i].topColor, cases[i].bottomColor, 223 program, bindingTarget, cases[i].depth, 224 cases[i].sourceSubRectangle, 225 cases[i].unpackImageHeight, 226 cases[i].rTextureCoord); 227 } 228 runNextVideo(); 229 } 230 runNextVideo(); 231 }); 232 } 233 234 runTexImageTest(gl.TEXTURE_3D).then(function(val) { 235 runTexImageTest(gl.TEXTURE_2D_ARRAY).then(function(val) { 236 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); 237 finishTest(); 238 }); 239 }); 240 } 241 242 return init; 243 }