- From: Jake Archibald <jaffathecake@gmail.com>
- Date: Sun, 22 Mar 2015 13:23:12 +0000
- To: Rik Cabanier <cabanier@gmail.com>, Ashley Gullen <ashley@scirra.com>
- Cc: WHATWG <whatwg@whatwg.org>, Ian Hickson <ian@hixie.ch>, Robert O'Callahan <robert@ocallahan.org>
On Sat, 21 Mar 2015 at 18:16 Rik Cabanier <cabanier@gmail.com> wrote: > Justin is worried that in order to make this asynchronous, Chrome has to > create a snapshot of the canvas bits which is slow if it resides on the GPU. > Of course, his workaround to use getImageData is just as slow since it has > to do the same operation. > > To alleviate this, I have 2 proposals: > - After calling toBlob, the canvas is read-only until the promise is > fulfilled > - If the user changes the canvas after calling toBlob, the promise is > cancelled. > > Maybe we should only allow 1 outstanding toBlob per canvas element too. > I don't really understand why we'd need these restrictions, can't this just operate like a queue? Copying from https://code.google.com/p/chromium/issues/detail?id=67587#c87: --- context.[drawing command]; // 1 context.[drawing command]; // 2 context.canvas.toBlob().then(callback); // 3 context.[drawing command]; // 4 var data = context.getImageData(…); // 5 context.[drawing command]; // 6 [browser frame] Lines 1 & 2 would queue up operations to manipulate canvas pixels, but they would not wait on those pixels being painted. The toBlob call (3) queues up an operation to create a blob of a PNG of the canvas state. This means the blob would be created once 1 & 2 have applied. 4 queues up another canvas pixel manipulation, explicitly after the creation of the blob. 5 synchronously waits on the operation queue to complete, which includes 1, 2, the creation of the blob in 3, and the operation in 4. Blocking here kinda sucks & feels much like a synchronous layout operation, but hey that's the API we have. Note: callback hasn't been called yet, as promise resolving is a microtask. 6 queues up an operation to manipulate the canvas. Then we reach the end of the microtask, callback is called with the blob, then we reach the end of the task. The next browser frame is blocked on the completion of 6. Without the synchronous step 5, the JS wouldn't block on paints (aside from callback). --- Sure, we now have 3 copies of the canvas data. One for the on-screen canvas, one for the blob (compressed as PNG), and another for the getImageData, but that's what I, the developer have asked for. If that's taking too much memory, or is slow, I should find another way to do what I'm trying to do. I've created intermediate frames through toBlob and getImageData, rather like how calling offsetWidth between two style modifications creates an intermediate style calc & layout. If that's not what I want, I shouldn't interleave my reads & writes.
Received on Sunday, 22 March 2015 13:23:38 UTC