On 2014-05-07, 12:34 PM, Ehsan Akhgari wrote:
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?
We had a meeting about this today, and there is one big issue with my
proposal above. Because of the fact that extra dictionary members in
the contextOptions arguments are ignored, this means that UA engines
which have already shipped their implementation will happily accept
|canvas.getContext("webgl", {version: 2})| and give you a context object
which doesn't support what the author would expect, which would fail
requirement 1 above.
After going through the options a bit, it seems like the only sensible
thing to do would be to use a new context name string, so that code
which is written against WebGL2 will not work against an implementation
which is unaware of this. We seemed to agree that "webgl2" would
probably be as good of an option as any. So basically the current state
of the proposal is to accept "webgl2" as the name of the context, return
a WebGLRenderingContext, and extend that interface in the spec through a
partial interface, making those methods throw "NotSupportedError" if you
have received the context with the name "webgl".
Sorry for the back and forth on this! What do people think of this
proposal version N? :-)
Cheers,
Ehsan
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform