On Sat, 21 Mar 2015 at 18:16 Rik Cabanier <caban...@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

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

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.

Reply via email to