On Tue, 13 Nov 2012, Gregg Tavares (社ç~T¨) wrote:
> > There is an output rectangle with dimensions w x h.This question is still important; IMHO the answer to this question is
> > There is a WebGL... I don't know, scene graph, which uses some
> > coordinates or other.
> > There has to be some mapping from the coordinate system used in the
> > WebGL, to the dimensions of the canvas.
> > Where is that mapping set?
related to where settings that apply to rendering to a specific canvas
element's bitmap should be.
My recommendation for WebGL would be to have an explicit method that
> The difference is in WebGL's default double buffered-ness. With Canvas
> 2D you'd always end up with either
> (a) a circle on top of a rectangle setTimeout->raf
> (b) a rectangle on top of a circle raf->SetTimeout
> With WebGL, because it's double buffered and cleared on each composite.
> You'll either get
> (a) a circle on top of a rectangle setTimeout->raf->composite
> (b) a rectangle on top of a circle raf->setTimeout->composite
> (c) a circle raf->composite->setTimeout->composite
> (d) a rectangle setTimeout->composite->raf->composite
> I'd prefer if the clear was tied to the current event exiting, not to
> the composite. That would get rid of 2 cases. with
> "preserveDrawingBuffer" = false. The default you'd get cases (c) and
> (d). With "preserveDrawingBuffer" = true, which makes WebGL act like
> canvas2d and is slow you'd get (a) and (b)
pushes the bits to the screen, and that would also clear the buffer. So
then (c) and (d) couldn't happen.
There's no waste. In practice, you don't actually need to implement the
> > > > I'm not a fan of a DrawingBuffer object because it's yet more
> > > > indirection, and we have a pile of indirection here already with
> > > > all the cross-worker canvas stuff. I could see having the contexts
> > > > implicitly have their own drawing buffer while they aren't bound
> > > > to a canvas, and having these buffers be reset (along with state,
> > > > in the 2D world, though not in GL) when you bind/unbind, but I
> > > > don't see why we'd want to explicitly have an object for this.
> > >
> > > We need canvas contents separate from contexts for all the reasons
> > > explained in previous posts.
> > The previous posts explained why a single WebGL context needs to be
> > able to paint its state in different configurations on different
> > canvases, as well as needing a way to generate off-screen images.
> > That seems quite compatible with having a drawing buffer per canvas,
> > plus a drawing buffer for contexts that aren't assigned to a canvas.
> Why waste the object?
drawing buffer for the context, you can just buffer up all the drawing
commands and push them at once to the actual screen bitmap. You only need
to actually instantiate the off-screen one when the author is using the
context to do an off-screen drawing (i.e. when they call commit() in the
absence of a canvas, assuming we only commit on explicit calls and not on
the spinning of the event loop).
It doesn't have to be instantiated if it's not used.
> If canvas all have a drawingBuffer then the most common use case is to
> create a context with no drawingBuffer or a 1x1 and then just draw to
> the mutliple canvas drawingbuffers. Why the wasted drawingBuffer on the
> context if it will rarely if ever be used?
With the CanvasProxy thing I'm currently writing up, you'll be able to
> I'm looking at it as each canvas has a drawingBuffer. You can't have a
> canvas in a worker but you can have a drawingBuffer.
have a canvas in a worker.
2D has always blown away state when you change bitmap dimensions.
> > > Why should 2D be different than GL?
> > For consistency with what happens today. GL doesn't blow away state,
> > 2D does. Changing this just because the contexts are bound differently
> > would just mean that different codepaths get radically different
> > results even though they end up doing the same thing.
> Why does 2D need to blow away state? The solution I was proposing no 2D
> state is blown away.
It blows away the context's bitmap, not the canvas'. Apologies for any
> Maybe I'm mis-understanding your proposal. You mentioned that attaching
> a context to a canvas blows away that canvas "bitmap".
At this stage there's three bitmaps in theory, though in practice none
> So this is what I'm imaging your proposal is.
> <canvas width="32" height="32" id="1"></canvas>
> <canvas width="64" height="64" id="2"></canvas>
> <canvas width="96" height="96" id="3"></canvas>
> c1 = document.getElementById("1");
> c2 = document.getElementById("2");
> c3 = document.getElementById("3");
are instantiated since nothing has been drawn.
> ctx = new Canvas2DRenderingContext()
Per my proposal (that I'm still trying to write up), ctx officially has
two 300x150 bitmaps at this stage, a "scratch" one that draws go to, and
an "output" one that is what would be used if you called drawImage().
However, the "scratch" one is really just a record of what is drawn, so
doesn't really need to exist as a bitmap, and the "output" bitmap is never
used, so it doesn't need to be instantiated.
So at this stage there's five virtual bitmaps and none have been
This drops the ctx "output" bitmap, instead using the c1 bitmap for that
purposes. ctx's scratch bitmap is cleared and resized to 32x32. Since this
is a 2D context, state is reset to initial values (as if today the canvas
dimensions were changed).
So at this stage there's four virtual bitmaps, and still none have been
instantiated. If we were to call fillRect() followed by commit(), then
there'd be one instantiated bitmap, the c1 bitmap.
Now ctx's output bitmap is realiased to c2's bitmap, and ctx's scratch
bitmap is resized and cleared again. In theory, ctx now has a 64x64
scratch bitmap and ctx's output bitmap is c2's bitmap.
At this stage, there's one instantiated bitmap, c1's. If we call
fillRect() followed by commit() again, then there's two, c1's and c2's.
In practice, if the canvases are always visible and not overlapped, there
might in fact be only one bitmap total: the bitmap for the whole display.
The fillRect() calls can all be painted straight into that one bitmap.
Even though there's three canvases.
The key is that there's a difference between the simplest way to describe
what's going on (which involves lots of bitmaps) and the most optimal
implementation (which in some cases can be just one bitmap). The important
thing to do is not expose the bitmaps that we want to keep in the
"theoretical" world. So for example, if drawImage() and getImageData()
only ever get data from the "output bitmap"s here, we can ensure that
there's never a need to actually instantiate the scratch bitmap.
Ian Hickson U+1047E )\._.,--....,'``. fL
http://ln.hixie.ch/ U+263A /, _.. \ _\ ;`._ ,.
Things that are impossible just take longer. `._.-(,_..'--(,_..'`-.;.'