| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| function logOutput(s) { |
| if (window.domAutomationController) |
| window.domAutomationController.log(s); |
| else |
| console.log(s); |
| } |
| |
| function sendResult(status) { |
| if (window.domAutomationController) { |
| window.domAutomationController.send(status); |
| } else { |
| console.log(status); |
| } |
| } |
| |
| // This is a very basic test for 4 corner pixels, with large tolerance. |
| function checkFourColorsFrame(video) { |
| const width = video.videoWidth; |
| const height = video.videoHeight; |
| let test_cnv = new OffscreenCanvas(width, height); |
| let ctx = test_cnv.getContext('2d'); |
| ctx.drawImage(video, 0, 0, width, height); |
| |
| const kYellow = [0xFF, 0xFF, 0x00, 0xFF]; |
| const kRed = [0xFF, 0x00, 0x00, 0xFF]; |
| const kBlue = [0x00, 0x00, 0xFF, 0xFF]; |
| const kGreen = [0x00, 0xFF, 0x00, 0xFF]; |
| |
| function checkPixel(x, y, expected_rgba) { |
| const settings = {colorSpaceConversion: 'none'}; |
| const rgba = ctx.getImageData(x, y, 1, 1, settings).data; |
| const tolerance = 30; |
| for (let i = 0; i < 4; i++) { |
| if (Math.abs(rgba[i] - expected_rgba[i]) > tolerance) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| let m = 10; // margin from the frame's edge |
| if (!checkPixel(m, m, kYellow)) { |
| logOutput('top left corner is not yellow'); |
| return false; |
| } |
| if (!checkPixel(width - m, m, kRed)) { |
| logOutput('top right corner is not red'); |
| return false; |
| } |
| if (!checkPixel(m, height - m, kBlue)) { |
| logOutput('bottom left corner is not blue'); |
| return false; |
| } |
| if (!checkPixel(width - m, height - m, kGreen)) { |
| logOutput('bottom right corner is not green'); |
| return false; |
| } |
| return true; |
| } |
| |
| function fourColorsFrame(ctx) { |
| const width = ctx.canvas.width; |
| const height = ctx.canvas.height; |
| const kYellow = '#FFFF00'; |
| const kRed = '#FF0000'; |
| const kBlue = '#0000FF'; |
| const kGreen = '#00FF00'; |
| |
| ctx.fillStyle = kYellow; |
| ctx.fillRect(0, 0, width / 2, height / 2); |
| |
| ctx.fillStyle = kRed; |
| ctx.fillRect(width / 2, 0, width / 2, height / 2); |
| |
| ctx.fillStyle = kBlue; |
| ctx.fillRect(0, height / 2, width / 2, height / 2); |
| |
| ctx.fillStyle = kGreen; |
| ctx.fillRect(width / 2, height / 2, width / 2, height / 2); |
| } |
| |
| function waitForNextFrame() { |
| return new Promise((resolve, _) => { |
| window.requestAnimationFrame(resolve); |
| }); |
| } |
| |
| function initGL(gl) { |
| gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); |
| gl.enable(gl.SCISSOR_TEST); |
| } |
| |
| function fourColorsFrameGL(gl) { |
| const width = gl.canvas.width; |
| const height = gl.canvas.height; |
| gl.scissor(0, 0, width, height); |
| gl.clearColor(0, 0, 0, 1); |
| gl.clear(gl.COLOR_BUFFER_BIT); |
| |
| gl.scissor(width / 2, 0, width, height / 2); |
| gl.clearColor(0, 1, 0, 1); |
| gl.clear(gl.COLOR_BUFFER_BIT); |
| |
| gl.scissor(width / 2, height / 2, width, height); |
| gl.clearColor(1, 0, 0, 1); |
| gl.clear(gl.COLOR_BUFFER_BIT); |
| |
| gl.scissor(0, 0, width / 2, height / 2); |
| gl.clearColor(0, 0, 1, 1); |
| gl.clear(gl.COLOR_BUFFER_BIT); |
| |
| gl.scissor(0, height / 2, width / 2, height); |
| gl.clearColor(1, 1, 0, 1); |
| gl.clear(gl.COLOR_BUFFER_BIT); |
| |
| gl.finish(); |
| } |
| |
| function setupFrameCallback(video) { |
| logOutput(`Expecting frames now`); |
| let vf_counter = 5; |
| function videoFrameCallback(now, md) { |
| logOutput(`Got a video frame: ${now}`); |
| if (vf_counter > 0) { |
| vf_counter--; |
| video.requestVideoFrameCallback(videoFrameCallback); |
| return; |
| } |
| |
| if (checkFourColorsFrame(video)) { |
| logOutput('Test completed'); |
| sendResult('SUCCESS'); |
| } else { |
| logOutput('Test failed. Result mismatch.'); |
| sendResult('FAILED'); |
| } |
| } |
| video.requestVideoFrameCallback(videoFrameCallback); |
| } |
| |
| async function runTest(context_type, alpha) { |
| const canvas = document.getElementById('cnv'); |
| const video = document.getElementById('vid'); |
| const ctx = canvas.getContext(context_type, {alpha: alpha}); |
| const fps = 60; |
| |
| let draw = null; |
| if (context_type == 'webgl2') { |
| initGL(ctx); |
| draw = fourColorsFrameGL; |
| } else { |
| draw = fourColorsFrame; |
| } |
| |
| draw(ctx); |
| let stream = canvas.captureStream(fps); |
| video.srcObject = stream; |
| video.onerror = e => { |
| logOutput(`Test failed: ${e.message}`); |
| sendResult('FAIL'); |
| }; |
| setupFrameCallback(video); |
| video.play(); |
| |
| while (true) { |
| await waitForNextFrame(); |
| draw(ctx); |
| } |
| } |