[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] using the same context with multiple canvases






On Sat, Nov 17, 2012 at 6:46 AM, Ian Hickson <ian@hixie.ch> wrote:

I've now specced the proposal for this; for details please see this post:

   http://lists.w3.org/Archives/Public/public-whatwg-archive/2012Nov/0199.html

It's not exactly as I was describing earlier, but it's pretty close.
(Turns out what I was proposing has some issues.)


On Wed, 14 Nov 2012, Gregg Tavares (社ç~T¨) wrote:
>
> Why do you want to blow away state? This seems like a perfectly reasonable
> thing to want to do
>
>    ctx.beginPath();
>    ctx.arc(...);
>    c1.setContext(ctx);
>    ctx.stroke();
>    c2.setContext(ctx);
>    ctx.stroke();
>    c3.setContext(ctx);
>    ctx.stroke();

I don't really understand why you would ever do that. Can you elaborate on
the use case?

Why would I want to do this? Because making paths is time consuming. Assume my path requires 1000 lines. Why would I want to have to repeat that N times?

    ctx.beginPath();
    for (var i = 0; i < 1000; ++i) {
      ctx.moveTo(...);
      ctx.lineTo(...);
   }
 
   c1.setContext(ctx);
   ctx.stroke();
   c2.setContext(ctx);
   ctx.stroke();
   c3.setContext(ctx);
   ctx.stroke();

Not only is it slow for _javascript_ to repeat the 1000 lines but it's slow for the 2d context implementation. It has to construct GPU geometry 3 times as well.There's no way for it to know ahead of time that you're going to generate the same input so it can't cache anything.

Handing difference sizes is easy. That's what transforms are for

   // draw in each context.
   [c1, c2, c3].forEach(function(canvas) {
      canvas.setContext(ctx);
      ctx.save();
      ctx.scale(canvas.width, canvas.height);
      ctx.stroke();
      ctx.restore();
   }

This is especially important in WebGL where you're trying to draw a top, front, side and perspective view. It's far more efficient to setup your model once (10-50 calls into the API) then drawing once on each view (3-4 calls per draw) than to have to do all the calls once per view.

    ctx.beginPath();
>    ctx.arc(...);
>    c1.setContext(ctx);
>    ctx.stroke();
>    c2.setContext(ctx);
>    ctx.stroke();
>    c3.setContext(ctx);
>    ctx.stroke();
 
I'm happy to support this if it makes sense, but in practice
I think it's saner not to do that. Complications include things like the
canvas bitmaps being different dimensions from each other (which do you
use? right now I resize the scratch bitmap to match the canvas bitmap),
what happens in the cross-worker case (what bitmap do you draw on, the
previous scratch bitmap, the canvas bitmap?), etc. By clearing the scratch
bitmap and state between each setContext() call, you solve a lot of these
problems cleanly, and it is consistent with what has always happened with
2D canvas whenever the dimensions are changed (which is conceptually
equivalent to binding to a new canvas, IMHO).


On Wed, 14 Nov 2012, Florian Bösch wrote:
> On Wed, Nov 14, 2012 at 1:03 AM, Ian Hickson <ian@hixie.ch> wrote:
> >
> > This question is still important; IMHO the answer to this question is
> > related to where settings that apply to rendering to a specific canvas
> > element's bitmap should be.
>
> GL contexts map via an affine transform set by the gl.viewport command
> in the form of left, top, width, height.

Ah, ok. That makes sense. I'd say that it also makes sense to put the
settings that apply to rendering to a specific canvas on the context too,
then.


> > My recommendation for WebGL would be to have an explicit method that
> > pushes the bits to the screen, and that would also clear the buffer.
> > So then (c) and (d) couldn't happen.
>
> I find this a noteworthy idea. Two remarks:
> 1) classically there exists a call in OpenGL called "flip" (which webgl
> does not have) which does exactly that in double buffering situations.
> 2) A call like it on a DrawingBuffer could help to flip exactly that
> drawing buffer you've actually drawn, avoiding to update drawing buffers
> which haven't actually been updated, and avoiding the preserveDrawingBuffer
> mess somewhat.

The way I specced the proposal for canvas is designed so that it should be
possible to implement this for WebGL. See the e-mail I cited above for the
hooks that WebGL would need to use to get this working.

--
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'