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

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






On Sun, Nov 11, 2012 at 8:15 AM, Ian Hickson <ian@hixie.ch> wrote:
On Sat, 10 Nov 2012, Chris Marrin wrote:
>
> If I create a context, not associated with a canvas, render to it, then
> associate it with a canvas, what happens?

For the 2D canvas, what I'm writing up in the proposal is that once you
commit (or once the event loop spins) the bitmap associated with the
context gets pushed to the canvas, along with the dimensions of the bitmap
(which affects the canvas element's intrinsic dimensions) and the
origin-clean flag (which affects whether you can read it).

That bitmap then remains, even if the context is moved to another canvas,
until such time as a context once again commits its bitmap (either
explicitly or through a spinning of the event loop).

With this model, it seems to me that you'd want to set the settings
current set with getContext()s second (and subsequent) argument(s) when
you create the context via the constructor, not when you set the context
to a canvas.


On Sat, 10 Nov 2012, Boris Zbarsky wrote:
> On 11/10/12 11:12 AM, Ian Hickson wrote:
> > In the current model, there's a one-to-one relationship, so the
> > question is moot.
>
> In the current model there is a one-to-many relationship between a
> canvas and canvas contexts.  In particular, it's possible to grab both a
> 2d context and a webgl context for the same canvas.

Not according to the spec, not for a long time. "webgl" and "2d" are
marked as incompatible, so once you get one, you can never get the other
for the same canvas element.

In current edits to the spec I'm going further and removing the built-in
support for contexts that are compatible with other contexts (as in '2d'
and 'opera-2d'), though I'm leaving a hook for proprietary contexts so
that they can be made to work if someone cares to spec it.


> > If you create a context using the constructor, you get a context and
> > it gets a backing store. If you then bind it to a canvas, the canvas
> > gets a separate backing store, and there's a method you invoke that
> > pushes the bits from the context to the canvas (this also happens
> > implicitly whenever the event loop spins). One way to distinguish the
> > two is to compare the results of drawImage() when passed a context vs
> > when passed a canvas. You can also see the difference between this
> > model and the shared bitmap model by drawing on the main thread and
> > then calling alert(); in the shared bitmap model the canvas will show
> > the drawing but in the split context model it will not.
>
> That seems like a possible way to do it, yes.  It does involve twice the
> memory usage, right?

I'm not sure, but I think so, yes. Or at least, another instance of the
bitmap buffer.

Right now as far as I can tell you need two copies of the bitmap per
canvas: one for drawing on, and one for painting to the screen, so that
you don't get any flicker. In the model with disconnected contexts you
need one for drawing on, still, and one for the screen, and you may need
one for the canvas in practice, depending on how exactly you composite.
However, since it can't be drawn on other than just replacing the entire
image, it may be possible to get away with not actually having an entire
second copy all the time? I'm not sure.


> > This split bitmap thing is needed because otherwise there's no way to
> > know when to actually update the screen bitmap in the case of the
> > context being on a different thread.
>
> Hmm.  Why not?  The other thread could send a message, in general,
> right?

Right, that's what the commit() method will be in the proposal. But that
means the worker can't be painting to the screen, you have to have a
separate bitmap for it to paint to.


On Sat, 10 Nov 2012, Chris Marrin wrote:
> >
> > What's the use case for getRenderingContext()?
>
> I have a canvas, I want to know what context is currently associated
> with it.

Why? What's the use case? What are you going to do with it?


If the canvas had it's own drawingbuffer and all the context does is provide an API to draw then you could do this

  function ThirdPartyLibrary() {
      var oldContext = canvas.getContext();
      canvas.setContext(contextThatBelongsToLibrary);
      drawStuffWithoutEffectingStateOfUsersContext();
      canvas.setContext(oldContext);
 }

I don't see the point i having a backstore associated with each context
instead of the canvas. That's not how  it works currently in Chrome for 
canvas 2d or needs to work in any browsers which is one of the things 
that led us to this design in the first place. 

Each canvas, 2d or 3d is just a framebuffer object (a texture and or depth+stencil). 
Being able to set which framebuffer object is currently being rendered to by calling 
setContext or as previously mentioned, gl.bindDrawingBuffer(canvas)
is the simplest solution and provides lots of benefits. Including the one above.

 

Note in particular that if the context is in another worker, and you're on
the main thread with the canvas, you're not going to be able to get the
actual context object anyway. The only place you can get the context
object is where you can set it, and since only you can set it, it seems
easy enough to keep track of it...


> I don't think it would be better to avoid a write-only API for the
> context.

You think it would be better to have a write-only API for the context?

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