On 2014-05-07, 11:40 AM, Vladimir Vukicevic wrote:
On Wednesday, May 7, 2014 9:20:18 AM UTC-4, Ehsan Akhgari wrote:
On 2014-05-07, 6:15 AM, Anne van Kesteren wrote:

WebGL is already following the OpenGL path.  Trying to make it more "webby" by 
trying to mush the APIs together isn't doing the web a favor since the API is already 
more OpenGL-like, isn't doing developers a favor since they now have to have this pile of 
getExtension() code around, and is definitely not doing us a favor, because we have to 
support the explosion of all combo of extensions.



Again, this seems like a false comparison. No need for an explosion of
extensions. Furthermore, what you're advocating will give us an
enormous API surface area long term, which we'll have to maintain and
test, even though most new content will not use it (they'll get the
newer classes).

So earlier I suggested feature detecting based on _a_ new WebGL2
feature, to which Benoit replied that is a bad idea since your code
would be testing something and assuming unrelated support of other
features based on that (which _is_ bad practice, but I thought is a goal
of the all-or-nothing approach of the WebGL2 API.)

So in response, I suggested making individual features feature
detectible (which is totally doable in your FOO/FROB/BLARG example BTW!)
to which you replied saying that is a bad idea since all of the features
are either supported or not (if I understand your response correctly.)


I think one possible middle ground would be to define the API as follows:

interface WebGL2RenderingContext : WebGLRenderingContext {
    // new methods go here
};

partial interface HTMLCanvasElement {
    (CanvasRenderingContext2D or
     WebGLRenderingContext or
     WebGL2RenderingContext) getContext(DOMString id, optional any
options = null);
};

Totally with you.  That's how the current implementation works.

And keep the string "webgl" as the name of the context.  This way, Web
content can do the following checks:

if (window.WebGL2RenderingContext) {
    // this browser supports the WebGL2 APIs
}

var ctx = canvas.getContext("webgl");

if (ctx instanceof WebGL2RenderingContext) {
    // I actually got a WebGL2 context, my hardware also supports it!
}

Ok, now you lost me for a bit.  Why is this better than:

var ctx = canvas.getContext("webgl2");
if (!ctx) {
   ctx = canvas.getContext("webgl");
   useWebGL1Renderer = true;
}

This will preserve the all-or-nothing-ness of the WebGL2 feature set, it
will not require maintaining different code paths depending on which set
of individual extensions are enabled, is completely forward/backward
compatible, and at least limits the API surface that we will need to
support forever.

WebGL 2 is a superset of WebGL 1.  So the API surface we need to support doesn't get any 
more complicated, except for explicit "is webgl2 in use" checks.  The actual 
C++ implementation has explicit inheritance even.

Doing getExtension("webgl2") seems weird, and also requires extra implementation work since we need to create 
the right kind of OpenGL context under the hood.  Currently we do that when we call getContext.  If we had to wait 
until getExtension("webgl2"), then we'd need to recreate the context.  To do that, we'd have to either define 
that you're not allowed to call any context API functions before calling getExtension("webgl2"), making that 
the only "extension" to have that limitation, or we'd need to trigger a context lost and require all content 
to wait for a content restored event in order to continue rendering.  This is added complexity both for developers and 
implementations for zero benefit.

In the future, there might be a WebGL 3 that's a complete API departure from 
WebGL 1/2, which would require a new context name anyway.

WebGL made an explicit decision to do things this way -- the one thing that I 
would go back and change is getExtension() returning an extension object, 
instead of acting as an enableExtension().  I don't remember *why* we did this, 
but I seem to recall some decent arguments for it.

There really isn't a good solution to this problem in general.  The Web has 
tried multiple things, including the WebGL approach.  All of them have a set of 
upsides and downsides; there isn't a perfect option.

I discussed the requirements of this API in person with vlad and bjacob. Here are two key things to keep in mind:

1. The WebGL working group wants web pages to opt in to the WebGL2 specific parts of the functionality explicitly. The issue is that some of the functionality exposed by WebGL2 is not currently available on mobile GPUs, and we don't want to design the API in a way that enables people to write code oblivious to this which works in their desktop browsers and then have the code break when people view those pages on mobile devices which do not provide hardware support for this.

2. Because of the way that the underlying OpenGL API works, we need to have the information on what kind of OpenGL context options we want to pass to the underlying platform APIs at the point that we create the underlying OpenGL context. That place is HTMLCanvasElement.getContext. Because the existing semantics of getContext mandates the implementation to return null if it doesn't support the functionality requested by the web page.

I think both of these requirements are reasonable. We discussed something that might be a solution:

1. The context name remains "webgl".

2. We add a |version| member to the contextOptions dictionary, that specifies the minimum required version of WebGL that's requested. Implementations are free to return a context that implements a higher version, should that be appropriate in the future, but never lower.

3. WebGLRenderingContext remains one interface, and gets extended with new methods/tokens to support additions to the API. If those methods aren't supported (because you only have a v1 API, for example), those methods throw "NotSupportedError".

4. Additionally, we will try to change the getExtension() mechanics so that all they do is enable existing methods on WebGLRenderingContext (i.e. make them stop throwing) and return the same context object, instead of returning an entirely new object. We'll kick off those discussions with the WebGL WG.

With this, if you request |version: 2| and the underlying GPU doesn't support WebGL 2, getContext returns null. In the future, for "WebGL3", the API would be extended in a similar way, and {version: 3} would now be accepted and that would make all of the WebGL2/3 parts of the API stop throwing "NotSupportedError" when you call them. With this, the need for feature detection also goes away because the underlying implementation guarantees that if you get a non-null result from getContext, then all of the APIs corresponding to that version will work fine. The returned context object may have additional APIs that will throw "NotSupportedError" once WebGL3 is implemented.

What do people think about this solution?

Cheers,
Ehsan
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to