这是indexloc提供的服务,不要输入任何密码
Skip to content

WebGPURenderingContext should support preserveDrawingBuffer: true #2743

@greggman

Description

@greggman

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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions