videoFrame-texImage.any.js (4691B)
1 // META: global=window,dedicatedworker 2 // META: script=/webcodecs/utils.js 3 // META: script=/webcodecs/webgl-test-utils.js 4 5 function testGLCanvas(gl, width, height, expectedPixel, assertCompares) { 6 var colorData = 7 new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4); 8 gl.readPixels( 9 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, 10 gl.UNSIGNED_BYTE, colorData); 11 assertCompares(gl.getError(), gl.NO_ERROR); 12 13 const kMaxPixelToCheck = 128 * 96; 14 let step = width * height / kMaxPixelToCheck; 15 step = Math.round(step); 16 step = (step < 1) ? 1 : step; 17 for (let i = 0; i < 4 * width * height; i += (4 * step)) { 18 assertCompares(colorData[i], expectedPixel[0]); 19 assertCompares(colorData[i + 1], expectedPixel[1]); 20 assertCompares(colorData[i + 2], expectedPixel[2]); 21 assertCompares(colorData[i + 3], expectedPixel[3]); 22 } 23 } 24 25 function testTexImage2DFromVideoFrame( 26 width, height, useTexSubImage2D, expectedPixel) { 27 let vfInit = 28 {format: 'RGBA', timestamp: 0, codedWidth: width, codedHeight: height}; 29 let argbData = new Uint32Array(vfInit.codedWidth * vfInit.codedHeight); 30 argbData.fill(0xFF966432); // 'rgb(50, 100, 150)'; 31 let frame = new VideoFrame(argbData, vfInit); 32 33 let canvas; 34 if (self.HTMLCanvasElement) { 35 canvas = document.createElement("canvas"); 36 canvas.width = width; 37 canvas.height = height; 38 } else 39 canvas = new OffscreenCanvas(width, height); 40 let gl = canvas.getContext('webgl'); 41 42 let program = WebGLTestUtils.setupTexturedQuad(gl); 43 gl.clearColor(0, 0, 0, 1); 44 gl.clearDepth(1); 45 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 46 gl.colorMask(1, 1, 1, 0); // Disable any writes to the alpha channel. 47 let textureLoc = gl.getUniformLocation(program, 'tex'); 48 49 let texture = gl.createTexture(); 50 51 // Bind the texture to texture unit 0. 52 gl.bindTexture(gl.TEXTURE_2D, texture); 53 54 // Set up texture parameters. 55 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 56 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 57 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 58 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 59 60 // Set up pixel store parameters. 61 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); 62 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); 63 64 // Upload the videoElement into the texture 65 if (useTexSubImage2D) { 66 // Initialize the texture to black first 67 gl.texImage2D( 68 gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, 69 null); 70 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, frame); 71 } else { 72 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, frame); 73 } 74 75 frame.close(); 76 77 assert_equals(gl.getError(), gl.NO_ERROR); 78 79 // Point the uniform sampler to texture unit 0 80 gl.uniform1i(textureLoc, 0); 81 82 // Draw the triangles 83 WebGLTestUtils.drawQuad(gl, [0, 0, 0, 255]); 84 85 // Wait for drawing to complete. 86 gl.finish(); 87 88 testGLCanvas(gl, width, height, expectedPixel, assert_equals); 89 } 90 91 function testTexImageWithClosedVideoFrame(useTexSubImage2D) { 92 let width = 128; 93 let height = 128; 94 let vfInit = 95 {format: 'RGBA', timestamp: 0, codedWidth: width, codedHeight: height}; 96 let argbData = new Uint32Array(vfInit.codedWidth * vfInit.codedHeight); 97 argbData.fill(0xFF966432); // 'rgb(50, 100, 150)'; 98 let frame = new VideoFrame(argbData, vfInit); 99 100 let canvas; 101 if (self.HTMLCanvasElement) { 102 canvas = document.createElement("canvas"); 103 canvas.width = width; 104 canvas.height = height; 105 } else 106 canvas = new OffscreenCanvas(width, height); 107 let gl = canvas.getContext('webgl'); 108 109 frame.close(); 110 if (useTexSubImage2D) { 111 gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, frame); 112 } else { 113 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, frame); 114 } 115 116 assert_equals(gl.getError(), gl.INVALID_OPERATION); 117 } 118 119 test(_ => { 120 testTexImage2DFromVideoFrame(48, 36, false, kSRGBPixel); 121 }, 'texImage2D with 48x36 srgb VideoFrame.'); 122 123 test(_ => { 124 testTexImage2DFromVideoFrame(48, 36, true, kSRGBPixel); 125 }, 'texSubImage2D with 48x36 srgb VideoFrame.'); 126 127 test(_ => { 128 testTexImage2DFromVideoFrame(480, 360, false, kSRGBPixel); 129 }, 'texImage2D with 480x360 srgb VideoFrame.'); 130 131 test(_ => { 132 testTexImage2DFromVideoFrame(480, 360, true, kSRGBPixel); 133 }, 'texSubImage2D with 480x360 srgb VideoFrame.'); 134 135 test(_ => { 136 testTexImageWithClosedVideoFrame(false); 137 }, 'texImage2D with a closed VideoFrame.'); 138 139 test(_ => { 140 testTexImageWithClosedVideoFrame(true); 141 }, 'texSubImage2D with a closed VideoFrame.');