215 lines
6.0 KiB
HTML
215 lines
6.0 KiB
HTML
<style>
|
|
canvas {
|
|
width: 300px;
|
|
height: 300px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<script id="vertexShaderSource" type="text/glsl">
|
|
attribute vec4 a_position;
|
|
varying vec2 v_texturePosition;
|
|
|
|
void main() {
|
|
v_texturePosition = vec2((a_position.x + 1.0) / 2.0, (a_position.y + 1.0) / 2.0);
|
|
gl_Position = a_position;
|
|
}
|
|
</script>
|
|
<script id="fragmentShaderSource" type="text/glsl">
|
|
precision mediump float;
|
|
|
|
varying vec2 v_texturePosition;
|
|
|
|
uniform sampler2D texture;
|
|
|
|
void main() {
|
|
gl_FragColor = texture2D(texture, v_texturePosition);
|
|
}
|
|
</script>
|
|
<script>
|
|
|
|
if (window.testRunner) {
|
|
testRunner.waitUntilDone();
|
|
testRunner.dumpAsText();
|
|
}
|
|
|
|
const width = 300;
|
|
const height = 300;
|
|
let canvas;
|
|
let gl;
|
|
let animationFrame = null;
|
|
let tested = false;
|
|
let drawFunction = null;
|
|
let video;
|
|
|
|
function output(msg) {
|
|
const div = document.getElementById("output");
|
|
div.innerHTML += `${msg}<br>`;
|
|
}
|
|
|
|
function isMostlyRed(buffer, x, y) {
|
|
let offset = (y * width + x) * 4;
|
|
return buffer[offset] > 240 && buffer[offset+1] < 25 && buffer[offset+2] < 25 && buffer[offset+3] > 240;
|
|
}
|
|
|
|
function isMostlyBlue(buffer, x, y) {
|
|
let offset = (y * width + x) * 4;
|
|
return buffer[offset] < 25 && buffer[offset+1] < 25 && buffer[offset+2] > 240 && buffer[offset+3] > 240;
|
|
}
|
|
|
|
function runTest() {
|
|
output("Checking the canvas pixels.");
|
|
|
|
drawFunction();
|
|
let pixels = new Uint8Array(width * height * 4);
|
|
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
|
|
|
if (isMostlyRed(pixels, 2, 2))
|
|
output("PASS: Bottom edge is red.");
|
|
else
|
|
output("FAIL: Bottom edge is not red.");
|
|
|
|
if (isMostlyBlue(pixels, 2, height - 2))
|
|
output("PASS: Top edge is blue.");
|
|
else
|
|
output("FAIL: Top edge is not blue.");
|
|
|
|
cancelAnimationFrame(animationFrame);
|
|
video.pause();
|
|
|
|
if (window.testRunner)
|
|
testRunner.notifyDone();
|
|
}
|
|
|
|
function init() {
|
|
|
|
canvas = document.querySelector("canvas");
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
|
|
gl = canvas.getContext("webgl");
|
|
|
|
gl.clearColor(0, 0, 0, 1);
|
|
|
|
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
|
|
gl.shaderSource(vertexShader, document.getElementById("vertexShaderSource").textContent);
|
|
gl.compileShader(vertexShader);
|
|
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
|
|
console.error("Vertex Shader failed to compile.");
|
|
console.log(gl.getShaderInfoLog(vertexShader));
|
|
return;
|
|
}
|
|
|
|
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
|
|
gl.shaderSource(fragmentShader, document.getElementById("fragmentShaderSource").textContent);
|
|
gl.compileShader(fragmentShader);
|
|
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
|
|
console.error("Fragment Shader failed to compile.");
|
|
console.log(gl.getShaderInfoLog(fragmentShader));
|
|
return;
|
|
}
|
|
|
|
let program = gl.createProgram();
|
|
gl.attachShader(program, vertexShader);
|
|
gl.attachShader(program, fragmentShader);
|
|
gl.linkProgram(program);
|
|
|
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
console.error("Unable to link shaders into program.");
|
|
return;
|
|
}
|
|
|
|
gl.useProgram(program);
|
|
let textureUniform = gl.getUniformLocation(program, "texture");
|
|
let positionAttribute = gl.getAttribLocation(program, "a_position");
|
|
gl.enableVertexAttribArray(positionAttribute);
|
|
|
|
let vertices = new Float32Array([
|
|
-1, -1,
|
|
1, -1,
|
|
1, 1,
|
|
1, 1,
|
|
-1, 1,
|
|
-1, -1
|
|
]);
|
|
|
|
let buffer = gl.createBuffer();
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
|
|
|
|
let updateTexture = function (texture, data) {
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
|
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
}
|
|
|
|
let texture = gl.createTexture();
|
|
|
|
video = document.createElement("video");
|
|
video.loop = true;
|
|
video.playsInline = true;
|
|
|
|
video.addEventListener("canplay", function () {
|
|
output("Video can play.");
|
|
}, false);
|
|
|
|
video.addEventListener("timeupdate", function () {
|
|
// If we've just started, jump forward to 3 seconds. If we've played a bit after
|
|
// that, check the pixels.
|
|
if (video.currentTime < 1) {
|
|
video.currentTime = 3;
|
|
return;
|
|
} else if (video.currentTime > 3.1) {
|
|
if (!tested)
|
|
runTest();
|
|
tested = true;
|
|
}
|
|
}, false);
|
|
|
|
/* Since the texImage2D call isn't flipping in Y, we'll load a
|
|
video that is already flipped. */
|
|
output("Setting video src.");
|
|
window.source = new MediaSource();
|
|
source.addEventListener('sourceopen', async event => {
|
|
var buffer = source.addSourceBuffer('video/mp4');
|
|
var response = await fetch('resources/orientation-flipped-fragmented.mp4');
|
|
buffer.appendBuffer(await response.arrayBuffer());
|
|
});
|
|
video.srcObject = source;
|
|
video.play();
|
|
|
|
drawFunction = function () {
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
|
|
if (video.currentTime > 0) {
|
|
updateTexture(texture, video);
|
|
}
|
|
|
|
gl.activeTexture(gl.TEXTURE0);
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.uniform1i(textureUniform, 0);
|
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
gl.vertexAttribPointer(positionAttribute, 2, gl.FLOAT, false, 0, 0);
|
|
|
|
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
|
|
animationFrame = requestAnimationFrame(drawFunction);
|
|
};
|
|
|
|
drawFunction();
|
|
}
|
|
|
|
window.addEventListener("load", init, false);
|
|
</script>
|
|
<body>
|
|
<canvas></canvas>
|
|
<div id="output">
|
|
</div>
|
|
</body>
|