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

Re: [Public WebGL] Some WebGL draft feedback



On Jan 6, 2010, at 4:25 AM, Philip Taylor wrote:

> On Wed, Jan 6, 2010 at 3:10 AM, Mark Callow <callow_mark@hicorp.co.jp> wrote:
>> I think we should not support simultaneous rendering by different APIs at
>> the first release. We can leave the door open so if there is great demand
>> for the feature it can be added in a future release. A restriction now that
>> canvas.getContext() destroys any existing context, thus preventing
>> simultaneous rendering, can easily be relaxed in the future without breaking
>> any applications.
> 
> Consider a situation where browsers don't support simultaneous
> rendering, and I write an application that needs to mix 2D and 3D, so
> I do something a bit slow and ugly with multiple canvases or some
> intermediate textures etc. Then one browser releases a new version
> that does support simultaneous rendering, so my application could be
> written more cleanly and efficiently. How do I use the new method in
> browsers that support simultaneous rendering, and fall back to the old
> method in the older browsers? If getContext silently destroys an
> existing context in old browsers, it seems very difficult for me to
> tell whether it's safe to use contexts simultaneously or not.

Right, this is the conversation we need to have here and with the HTML5 WG. What is the semantics of getContext()?

> 
> So the feature should be designed in such a way that it's easy to test
> for the feature in future browsers. (And it should be easy to test for
> the similar feature between any pair or set of contexts that are
> defined in the future, not just 2D+WebGL). Maybe it should just throw
> an exception if you try to use incompatible contexts - if you've
> already called getContext('2d') then the getContext('webgl') call will
> throw, and vice versa, if the browser doesn't support simultaneous
> rendering. That makes it easy to detect in script. That also prevents
> authors getting confused by drawing to one context and not seeing the
> output because the other context is being drawn instead, with no error
> message to indicate the problem. It also makes extension contexts like
> opera-2dgame fit easily within the model: it's compatible with the 2d
> context, but incompatible with the 3d context, so you can't mix them
> incorrectly. And it prevents all the questions about what happens if
> you try to use both 2d and webgl contexts (in a browser that doesn't
> support simultaneous rendering) and then use getImageData and
> glReadPixels and drawImage(canvas) and glTexImage2D(canvas) and
> toDataURL - now the canvas will only ever have a single bitmap (though
> it might be 'owned' by either the 2d or webgl contexts), so there's no
> longer a question of which bitmap the methods access.

Your proposal, throwing when you try to change APIs is pretty good, but I'm not a big fan of using exceptions as a way of determining features. Perhaps a better approach would be to return null instead of throwing.

I recently proposed that an alternative to simultaneous rendering is to preserve the color buffer data when switching APIs. Perhaps all these problems could be solved if we just added a locking mechanism to Canvas. It would work like this:

If simultaneous rendering is not supported then attempting to do a getContext() for an API after a different API has been gotten for that Canvas returns null, and the originally gotten context is still valid. This provides no way of switching the rendering API on a given Canvas. I think that's fine for a first implementation. You can always destroy and recreate the Canvas element if need be.

If simultaneous rendering is supported then attempting to do a getContext() for an API after a context for a different API has been gotten returns the context for the new API, enables it for rendering to the Canvas and disables the previously enabled context. Attempting to make any API calls on a disabled context throws an exception.When the new context is gotten, the color buffer from the previous context remains valid, but any other buffers (such as depth and stencil buffers) are removed. When the the context with these buffers is again gotten, the extra buffers are initialized as though this were the first call to getContext() for this API. After the first getContext() call to get a given context, all subsequent calls to get that same context are guaranteed to return the same object.

That description leaves a lot to be desired, so here's an example which will hopefully clear things up. I'll use Gregg's example:

	var ctx2d = canvas.getContext("2d");			// ctx2d is now enabled, Canvas is initialized to transparent black
	ctx2d.drawImage(someFlowerImage, 0, 0); 		// Canvas now contains flower image

	// Blur out the flowers
	var ctxFilter = canvas.getContext("filters");		// ctx2d is disabled, ctxFilter is enabled, Canvas has flower image
	if (!ctxFilter) {
		// Oh well, simultaneous rendering not supported
		return;
	}
	ctxFilter.radialBlur(50.5);						// flower image is blurred

	// Draw some text on a curve
	var ctxWordArt = canvas.getContext("word-art");	// ctxFilter is disabled, ctxWordArt is enabled, Canvas has a blurred flower image
	ctxWordArt.setColor(0, 0, 0);
	ctxWordArt.defineCurvePath([100, 100, 150, 50, 200, 300, 400]);
	ctxWordArt.drawTextAlongCurve("Hello world");	// Canvas now has "Hello World" on top of the blurred flower

	// Blur out the text we just drew
	canvas.getContext("filters");					// ctxWordArt is disabled, ctxFilter is enabled
	ctxFilter.zoomBlur(0.5);						// Flower is more blurry, text is also blurry

	// Draw the text again clearly on top of the blurred text.
	canvas.getContext("word-art");				// ctxFilter is disabled, ctxWordArt is enabled
	ctxWordArt.setColor(255, 0, 0);
	ctxWordArt.drawTextAlongCurve("Hello world");	// Canvas now has really blurry flower, blurred text and sharp text over it

The only difference between this and Gregg's example is that I check to see if simultaneous rendering is supported and I added a couple of getContext() calls to switch the enabled context. You'll notice that on the subsequent getContext() calls, I didn't bother assigning their value because we would guarantee that it would return the same object reference.

This is nice in a few ways:

1) No API change, just a change in the semantics
2) getContext() gives us a nice synchronization point
3) Support is optional, this won't hold up current implementations
4) The semantics about what the canvas buffer contains after the switch is clear

> 
> (The concept of incompatible contexts should be defined in HTML5,
> since it's not specific to WebGL - the editor has said he'd be happy
> to change what HTML5 currently defines, if someone tells him what it
> should say instead.)

That's a very useful bit of information. Do you think the HTML5 Editor (and other interested parties) would want to discuss the issues here?

-----
~Chris
cmarrin@apple.com




-----------------------------------------------------------
You are currently subscribe to public_webgl@khronos.org.
To unsubscribe, send an email to majordomo@khronos.org with
the following command in the body of your email: