[whatwg] Canvas in workers

Glenn Maynard glenn at zewt.org
Sun Oct 20 08:29:45 PDT 2013

On Sat, Oct 19, 2013 at 10:11 AM, Robert O'Callahan <robert at ocallahan.org>wrote:

> It's not clear to me how attachToCanvas works. An application like Google
> Maps wants to draw to multiple canvases from a worker and then render the
> updated canvas contents all at once, in synchrony with changes to the DOM
> made by the main thread. How would you do that with attachToCanvas?

That's not the problem attachToCanvas tries to solve.  It tries to solve
rendering to multiple canvases, without requiring synchronization with the
UI thread.  I have a proposal for handling synchronization with DOM
updates, but I'll post it in a separate thread.

(To clarify, this thread is talking about three different things: rendering
from a worker to the UI thread, rendering to multiple canvases, and
synchronizing rendering in a worker to DOM updates in the main thread.  The
only reason they're in the same thread is because some proposals are trying
to handle two or all three of them together.  Trying to do that is leading
to unwanted limitations, such as forcing synchronization when you don't
want it, and it's making the conversation hard to follow.  Since my
proposal is orthogonal to the rest--it's separate and compatible with both
WorkerCanvas and attachToCanvas--and this thread is discussing too many
things at once, I'll move the third to a separate thread.)

 - If you're rendering in a worker and the eventual target is in the main
>> thread, the worker needs to be careful to not start rendering again until
>> the main thread has assigned the ImageBitmap to where it wants it, and
>> called .close().  You'd need to send a message back to the worker going
>> "okay, you can continue now".  Otherwise, you'd start rendering before a
>> buffer has been freed up for reuse, and end up creating more backbuffers
>> than you intended (which matters for large screens).  This seems easy to
>> get wrong, and attachToCanvas doesn't have this problem.
> Not if you use transferToImageBitmap.

transferToImageBitmap does have this problem.  If you transferToImageBitmap
to detach your backing store to display it somewhere, then start rendering
the next frame without waiting for the ImageBitmap to be given to the
target, then as soon as you start rendering you'll end up creating a 3rd
rendering buffer.

(The present() proposal also has this problem, but users are only affected
by it if they're actually synchronizing to DOM updates.)

> With attachToCanvas, you just size both canvases normally
>> once, and switch between them with a single function call.
> I'm not sure how helpful this is. In the case of WebGL, the rendering
> context has resources that need to be sized the same as the destination
> color buffer, so they'll need to be resized anyway if you're actually using
> a single context to render to canvases of different sizes. My guess is that
> the advice will always be "don't do that".

If you think that a single context outputting to multiple canvases
fundamentally won't work well with canvases of different sizes, then forget
about the feature.

When you attachToCanvas, you're attaching that canvas's rendering buffer,
not just its color buffer.  In WebGL terms, each canvas is a Framebuffer,
with all its associated Renderbuffers.  Attaching the context to a canvas
is like using bindFramebuffer to render to its backing store.

> I believe these are minor changes, especially compared to moving drawing
> to a worker.

Moving drawing to a worker is unrelated to drawing to multiple canvases.  I
don't agree that it's a minor change: today you can create a black-box API
that renders to a context, without caring about the DOM at all.  If you
have to move the image to an <img> to display it, suddenly you have to care
about the DOM to render.  It breaks the basic model.

Glenn Maynard

More information about the whatwg mailing list