blob: e4bbe681313bc8946d0c2b0b77136102e50c1969 [file] [edit]
<!DOCTYPE html>
<script src=../../resources/js-test-pre.js></script>
<script>
var jsTestIsAsync = true;
if (window.testRunner)
testRunner.dumpAsText();
description("Check that GPU process ImageBuffer resource limits are enforced");
// Waits until getImageBufferResourceLimits() returns values that match the
// specified query. We do this because there is asynchrony involved in
// these values (from IPC messages and the use of atomics), so cannot guarantee
// that we will get the values we expect at the exact time of the call.
async function imageBufferResourceLimitsMatch(query) {
for (;;) {
let limits = await internals.getImageBufferResourceLimits();
let queryMatched = true;
for (let key in query) {
let queryValue = query[key];
if (typeof queryValue == "number") {
if (limits[key] != queryValue)
queryMatched = false;
} else {
if (!query[key](limits[key]))
queryMatched = false;
}
}
if (queryMatched)
return true;
}
}
function checkLimits(limits) {
return limits.acceleratedImageBufferForCanvasLimit >= 1000 &&
(limits.globalAcceleratedImageBufferLimit - limits.acceleratedImageBufferForCanvasLimit) >= 1000 &&
(limits.imageBufferForCanvasLimit - limits.globalAcceleratedImageBufferLimit) >= 1000 &&
(limits.globalImageBufferForCanvasLimit - limits.imageBufferForCanvasLimit) >= 1000;
}
function growCanvasesTo(canvases, count) {
debug(`Increasing canvas count to ${count}`);
while (canvases.length < count) {
let e = document.createElement("canvas");
e.width = 10;
e.height = 10;
canvases.push(e);
}
}
function shrinkCanvasesTo(canvases, count) {
debug(`Decreasing canvas count to ${count}`);
canvases.length = count;
}
function getEffectiveRenderingModeCounts(canvases) {
let accelerated = 0;
let unaccelerated = 0;
let noBackend = 0;
for (let c of canvases) {
let m = c.getContext("2d").getEffectiveRenderingModeForTesting();
if (m == "Accelerated")
++accelerated;
else if (m == "Unaccelerated")
++unaccelerated;
else if (m === null)
++noBackend;
}
return { accelerated, unaccelerated, noBackend };
}
async function run() {
if (!window.internals) {
debug("Test requires internals");
return;
}
// First, wait until any canvases from previous tests have been deleted.
gc();
try {
await imageBufferResourceLimitsMatch({ imageBufferForCanvasCount: 0 });
} catch {
debug("Platform does not enforce ImageBuffer resource limits");
return;
}
// Check that the hard code limits are reasonable enough for this test to
// rely on.
let limits = await internals.getImageBufferResourceLimits();
shouldBeTrue(() => checkLimits(limits));
let canvases = [];
let renderingModeCounts;
// Create 500 canvases. This is below acceleratedImageBufferForCanvasLimit,
// so should they should all get accelerated ImageBuffer backing stores.
growCanvasesTo(canvases, 500);
renderingModeCounts = getEffectiveRenderingModeCounts(canvases);
shouldEvaluateTo(() => renderingModeCounts.accelerated, 500);
shouldEvaluateTo(() => renderingModeCounts.unaccelerated, 0);
shouldEvaluateTo(() => renderingModeCounts.noBackend, 0);
// Wait until the values returned by getImageBufferResourceLimits match our
// expectations.
await imageBufferResourceLimitsMatch({
acceleratedImageBufferForCanvasCount: 500,
globalAcceleratedImageBufferCount: x => x >= 500,
imageBufferForCanvasCount: 500,
globalImageBufferForCanvasCount: 500,
});
// Create enough canvases to reach the per Web Process
// acceleratedImageBufferForCanvasLimit.
growCanvasesTo(canvases, limits.acceleratedImageBufferForCanvasLimit);
renderingModeCounts = getEffectiveRenderingModeCounts(canvases);
shouldEvaluateTo(() => renderingModeCounts.accelerated, limits.acceleratedImageBufferForCanvasLimit);
shouldEvaluateTo(() => renderingModeCounts.unaccelerated, 0);
shouldEvaluateTo(() => renderingModeCounts.noBackend, 0);
await imageBufferResourceLimitsMatch({
acceleratedImageBufferForCanvasCount: limits.acceleratedImageBufferForCanvasLimit,
globalAcceleratedImageBufferCount: x => x >= limits.acceleratedImageBufferForCanvasLimit,
imageBufferForCanvasCount: limits.acceleratedImageBufferForCanvasLimit,
globalImageBufferForCanvasCount: limits.acceleratedImageBufferForCanvasLimit,
});
// Create a few more canvases over the per Web Process
// acceleratedImageBufferForCanvasLimit. These should all be unaccelerated.
growCanvasesTo(canvases, limits.acceleratedImageBufferForCanvasLimit + 500);
renderingModeCounts = getEffectiveRenderingModeCounts(canvases);
shouldEvaluateTo(() => renderingModeCounts.accelerated, limits.acceleratedImageBufferForCanvasLimit);
shouldEvaluateTo(() => renderingModeCounts.unaccelerated, 500);
shouldEvaluateTo(() => renderingModeCounts.noBackend, 0);
await imageBufferResourceLimitsMatch({
acceleratedImageBufferForCanvasCount: limits.acceleratedImageBufferForCanvasLimit,
globalAcceleratedImageBufferCount: x => x >= limits.acceleratedImageBufferForCanvasLimit,
imageBufferForCanvasCount: limits.acceleratedImageBufferForCanvasLimit + 500,
globalImageBufferForCanvasCount: limits.acceleratedImageBufferForCanvasLimit + 500,
});
// Create an ImageBuffer with a non-canvas purpose and requested to be
// accelerated. Since we haven't reached globalAcceleratedImageBufferLimit,
// this should be accelerated.
let nonCanvasImageBufferRenderingMode = internals.getEffectiveRenderingModeOfNewlyCreatedAcceleratedImageBuffer();
shouldBeTrue(() => nonCanvasImageBufferRenderingMode == "Accelerated");
// Create enough canvases to reach the per Web Process
// imageBufferForCanvasLimit.
growCanvasesTo(canvases, limits.imageBufferForCanvasLimit);
renderingModeCounts = getEffectiveRenderingModeCounts(canvases);
shouldEvaluateTo(() => renderingModeCounts.accelerated, limits.acceleratedImageBufferForCanvasLimit);
shouldEvaluateTo(() => renderingModeCounts.unaccelerated, limits.imageBufferForCanvasLimit - limits.acceleratedImageBufferForCanvasLimit);
shouldEvaluateTo(() => renderingModeCounts.noBackend, 0);
await imageBufferResourceLimitsMatch({
acceleratedImageBufferForCanvasCount: limits.acceleratedImageBufferForCanvasLimit,
globalAcceleratedImageBufferCount: x => x >= limits.acceleratedImageBufferForCanvasLimit,
imageBufferForCanvasCount: limits.imageBufferForCanvasLimit,
globalImageBufferForCanvasCount: limits.imageBufferForCanvasLimit,
});
// Create a few more canvases over the per Web Process
// imageBufferForCanvasLimit. These should all fail to create a backend.
growCanvasesTo(canvases, limits.imageBufferForCanvasLimit + 500);
renderingModeCounts = getEffectiveRenderingModeCounts(canvases);
shouldEvaluateTo(() => renderingModeCounts.accelerated, limits.acceleratedImageBufferForCanvasLimit);
shouldEvaluateTo(() => renderingModeCounts.unaccelerated, limits.imageBufferForCanvasLimit - limits.acceleratedImageBufferForCanvasLimit);
shouldEvaluateTo(() => renderingModeCounts.noBackend, 500);
// Release all the canvases except for the initial 500 accelerated ones.
shrinkCanvasesTo(canvases, 500);
gc();
await imageBufferResourceLimitsMatch({
acceleratedImageBufferForCanvasCount: 500,
globalAcceleratedImageBufferCount: x => x >= 500,
imageBufferForCanvasCount: 500,
globalImageBufferForCanvasCount: 500,
});
// Create another 100 canvases, which all should be accelerated.
growCanvasesTo(canvases, 600);
renderingModeCounts = getEffectiveRenderingModeCounts(canvases);
shouldEvaluateTo(() => renderingModeCounts.accelerated, 600);
shouldEvaluateTo(() => renderingModeCounts.unaccelerated, 0);
shouldEvaluateTo(() => renderingModeCounts.noBackend, 0);
}
onload = async function() {
await run();
finishJSTest();
};
</script>
<script src=../../resources/js-test-post.js></script>