-
Notifications
You must be signed in to change notification settings - Fork 344
Description
My understanding is that currently, the thinking is there will be no preseveDrawingBuffer attribute for the WebGPURenderingContext
I don't know if this is a compelling use case for preserveDrawingBuffer but ... many products use something like html2canvas(25k stars) to generate screenshots for feedback/bugreports. I don't know what library Google uses but as an example, most Google apps have a feedback form and most of those forms generate a screenshot with AFAIK, some similar library.
To do this they need to be able to call toDataURL or toBlob on all canvases. In general, in WebGL and WebGPU, every canvas has 2 buffers, a drawingBuffer and a displayBuffer. toDataURL, toBlob, texImage2D, and createImageBitmap all read from the drawingBuffer. The displayBuffer is never exposed to the app (it's used by the browser's compositor). When preseveDrawingBuffer is false, t the drawingBuffer is cleared on composite. When composite happens is undefined but basically with preserveDrawingBuffer is false, the only safe time to call toDataURL or toBlob or any of those other functions is before exiting the current event.
Without preserveDrawingBuffer: true, it seems difficult to do support use cases like html2canvas. Off the top of my head they would have to insert themselves into the render loop of every library on every canvas so that when that render loop exits they can grab a copy. Further, they can't just augment requestAnimationFrame and grab a copy at the end. Instead they'd have to wrap every possible event since rendering might happen on setTimeout, setInterval, mouseMove, touchMove, pointerMove, click, fetch completion, a message from a worker, etc...
If preserveDrawingBuffer exists, the easy way for them to support html2cavnas is to patch getContext with something like
HTMLCanvasElement.prototype.getContext = function(origFn) {
return function(type, attribs, ...args) {
const newAttribs = {...(attribs || {}), {preserveDrawingBuffer: true}}
return origFn.call(this, type, newAttribs, ...args);
};
}(HTMLCanvasElement.prototype.getContext);
A counter argument is you could say they're required to re-architect their app so they can do something like
function takeScreenshot() {
// in a single event, call every library that renders to a canvas so that its content
// is available since it will be cleared when this event exits.
renderMap();
renderGraph();
renderDoc();
renderDiagram();
const screenshot = html2cavnasLib();
}
I suspect that's a huge ask for many devs who start off without that architecture and then later want to add screenshot support for feedback and would like it to be as painless as possible and don't really want to have to re-architect or patch 3rd party libraries.