blob: 2a9ac7caabaef409c16be5f6cbd1bcce0f063153 [file] [log] [blame] [edit]
// Code for performing browser reftest where we compare generated canvas
// image with an expected output image.
//
// This code expects the reftestRebaseline global to exist.
// See make_reftest in test/common.py.
// We have some tests that don't perform rendering during `main` so
// the normal process of performing `doReftest` in `postRun` doesn't
// work. These tests can delay the call to `doReftest` by calling
// `reftestBlock` and then calling `reftestUnblock` once they have
// done their rendering.
var reftestBlocked = false;
function reftestBlock() {
reftestBlocked = true;
}
function reftestUnblock() {
reftestBlocked = false;
doReftest();
}
function doReftest() {
if (reftestBlocked) return;
if (doReftest.done) return;
if (reportResultToServer.reported) return;
doReftest.done = true;
var img = new Image();
img.onload = () => {
assert(img.width == Module['canvas'].width, `Invalid width: ${Module['canvas'].width}, should be ${img.width}`);
assert(img.height == Module['canvas'].height, `Invalid height: ${Module['canvas'].height}, should be ${img.height}`);
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
var expected = ctx.getImageData(0, 0, img.width, img.height).data;
var actualUrl = Module['canvas'].toDataURL();
var actualImage = new Image();
actualImage.onload = () => {
/*
document.body.appendChild(img); // for comparisons
var div = document.createElement('div');
div.innerHTML = '^=expected, v=actual';
document.body.appendChild(div);
document.body.appendChild(actualImage); // to grab it for creating the test reference
*/
var actualCanvas = document.createElement('canvas');
actualCanvas.width = actualImage.width;
actualCanvas.height = actualImage.height;
var actualCtx = actualCanvas.getContext('2d');
actualCtx.drawImage(actualImage, 0, 0);
var actual = actualCtx.getImageData(0, 0, actualImage.width, actualImage.height).data;
var total = 0;
var width = img.width;
var height = img.height;
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
total += Math.abs(expected[y*width*4 + x*4 + 0] - actual[y*width*4 + x*4 + 0]);
total += Math.abs(expected[y*width*4 + x*4 + 1] - actual[y*width*4 + x*4 + 1]);
total += Math.abs(expected[y*width*4 + x*4 + 2] - actual[y*width*4 + x*4 + 2]);
}
}
// floor, to allow some margin of error for antialiasing
var wrong = Math.floor(total / (img.width*img.height*3));
if (wrong || reftestRebaseline) {
// Generate a png of the actual rendered image and send it back
// to the server.
Module['canvas'].toBlob((blob) => {
sendFileToServer('actual.png', blob);
reportResultToServer(wrong);
})
} else {
reportResultToServer(wrong);
}
};
actualImage.src = actualUrl;
}
img.src = 'expected.png';
};
function setupRefTest() {
Module['postRun'] = doReftest;
if (typeof WebGLClient !== 'undefined') {
// trigger reftest from RAF as well, needed for workers where there is no pre|postRun on the main thread
var realRAF = window.requestAnimationFrame;
/** @suppress{checkTypes} */
window.requestAnimationFrame = (func) => {
return realRAF(() => {
func();
realRAF(doReftest);
});
};
// trigger reftest from canvas render too, for workers not doing GL
var realWOM = worker.onmessage;
worker.onmessage = (event) => {
realWOM(event);
if (event.data.target === 'canvas' && event.data.op === 'render') {
realRAF(doReftest);
}
};
}
}
setupRefTest();