[Public WebGL] Some WebGL draft feedback

Chris Marrin [email protected]
Thu Jan 7 14:26:47 PST 2010

On Jan 7, 2010, at 11:35 AM, Kenneth Russell wrote:

>> ...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?
> This topic was discussed on today's conference call. Here's a summary
> of the points:
> 1) There was general agreement that supporting multiple simultaneous
> contexts on the canvas is useful to the developer.
> 2) There was agreement that interoperability between various contexts
> can be achieved in the worst case by reading back the framebuffer into
> system memory, and that optimizations can be done to achieve higher
> performance without changing the public APIs or forcing the developer
> to re-fetch contexts from the canvas to indicate which one is current.
> Exactly what information would be shared among various contexts would
> need to be more precisely specified. Today, only the color planes
> would be shared between the 2D and WebGL contexts, for example. There
> are open questions about the state of things like the stencil and
> depth buffers if first WebGL content is drawn and then 2D content is
> drawn, in particular if future 2D context implementations are fully
> hardware accelerated.
> 3) There was a desire to not require support for simultaneous contexts
> in the first release of the WebGL specification. (Multiple context
> support really needs to be defined in the HTML5 Canvas specification,
> anyway, and not the WebGL specification.) Consequently, we need to
> think about how to make it easy for the developer to query whether
> multiple contexts are supported, and not make API design decisions
> that would prevent introduction of multiple context support in the
> future.
> Kenneth Waters pointed out that in EGL, requests to render using
> multiple APIs (like OpenGL and OpenVG) need to be made at context and
> surface creation time. Therefore, to make sure we don't inhibit
> hardware accelerated implementations of multiple contexts on the
> canvas, we would need to make sure that all of the requests for
> multiple contexts are made early. This would also make it easier for
> the developer to write fallback paths in the case that multiple
> contexts aren't supported.
> One suggestion that was discussed is to return null from getContext()
> if it's called more than once and if the implementation doesn't
> support multiple contexts. This is most compatible with the current
> HTML5 Canvas API; see
> http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-canvas-getcontext
> . If the implementation does support multiple contexts, the developer
> would be required to fetch all of the contexts they intend to render
> with up front, before doing any rendering with any of them. This would
> allow WebGL implementations to allocate the rendering surface and
> context lazily, and to add in any context creation flags necessary to
> support hardware accelerated rendering from multiple APIs.
> Here's an example of this in use:
>    // Fetch all contexts; this is done once at application startup
>    var ctx2d = canvas.getContext("2d");
>    var gl = canvas.getContext("webgl");
>    var filters = canvas.getContext("filters");
>    // Use of contexts in rendering loop
>    gl.drawElements(...);  // Draw 3D model
>    filters.radialBlur(0.5);  // Bloom filter
>    ctx2d.fillText("Score: " + score, 10, 10); // Overly current score
> on 3D rendering
> Here's a negative example:
>    var gl = canvas.getContext("webgl");
>    gl.drawElements(...);  // Rendering has been done with this context
>    var ctx2d = canvas.getContext("2d");  // Returns null because all
> contexts weren't fetched before rendering was done
> If we can agree that this is a reasonable model, I'll update Section
> 2.1 to take it into account.

I think this is close. But I'm still concerned about the implicit sync point that happens when you call one rendering API after having used the other. I think it will lead to user confusion ("why did things get so much slower when I just added a string of text to the canvas? I guess text rendering is just really slow.") and bad habits. If users do [2D call, 3D call, 2D call, 3D call] it will be very slow but it's not clear why. If they do [enable2D, 2D call, enable3D, 3D call, enable2D, 2D call, enable3D, 3D call], it will be much more clear that the better approach is [enable 2D, 2D call, 2D call, enable 3D, 3D call, 3D call]. It is a more purposeful API and is more helpful to authors.

As Kenneth Waters pointed out, we don't NEED to have a synch mechanism, but I think it makes a better API. But I also agree that using getContext() for this unnecessarily overloads that call, so an explicit enable(...) call would be better. 

[email protected]

You are currently subscribe to [email protected]
To unsubscribe, send an email to [email protected] with
the following command in the body of your email:

More information about the public_webgl mailing list