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

Re: [Public WebGL] Help with the WebGL Context Lost specification



On Sat, Nov 12, 2011 at 9:59 AM, Glenn Maynard <glenn@zewt.org> wrote:
Note that this message uses HTML formatting.  Careful use of formatting helps spec readability a lot, and I strongly recommend reading this message in its formatted form, even if you normally view email in plain text.

Sorry that this became so long.


On Sat, Nov 12, 2011 at 6:23 AM, Gregg Tavares (wrk) <gman@google.com> wrote:
We're trying to finalize the WebGL specification for how context lost is handled

Not being a spec writer and not being familiar with every nuance of the HTML5 specs we're having a hard time figuring out the exact wording to attempt to make it 100% clear what needs to happen

Based on Cedric's changes my latest attempt is here:


I'd previously sketched out language for context creation, context loss and context restoration during earlier discussions, but they never came to any decision so I never finished them.  This is based on one version of that.  I do think those three things should be specced together, since they're tightly linked.

(cut here)

I echo Gregg's thanks for helping with this.

CC'ing Chris Marrin directly to bring this to his attention.

Looks great so far. Comments inline.

 
Each WebGLRenderingContext has a drawing buffer lost flag, which is initially unset.
Each WebGLRenderingContext has an associated canvas, set upon creation, that is a canvas.
Each WebGLRenderingContext has context creation parameters, set upon creation, which is an object.

To fire a WebGL context event named e means that an event using the WebGLContextEvent interface, with its type attribute initialized to e, and its isTrusted attribute initialized to true, is to be dispatched at the given object.

When the getContext() method of a canvas element is to return a new object for the contextId webgl, the user agent must perform the following steps:

1. Create a new WebGLRenderingContext object, context.
2. Let context's canvas be the context the getContext() method is associated with.

"be the context" -> "be the canvas"
 
3. If getContext() was invoked with a second argument, options, let context's context creation parameters be options, otherwise let it be the empty object, {}.
4. Create a drawing buffer using the settings specified in context's context creation parameters, and associate the drawing buffer with context.

We'll need to integrate the language from section 2.1 and 2.2 about handling of context creation parameters, buffers attached to the drawing buffer, etc. Perhaps these new steps can go at the beginning of Section 5.13 as you suggested, we can delete a little language from Section 2, and refer to Section 2 to define creation of the drawing buffer. Or perhaps we can rewrite section 2 to mainly comprise your steps, and delete most of Section 5.14. Do you have a preference?

We'll need to add another step indicating that if creation of the drawing buffer fails, a webglcontextcreation error is fired at the canvas.

5. Return context.

When the user agent detects that the drawing buffer associated with a WebGLRenderingContext context has been lost, it must run the following steps:

1. Let canvas be the canvas object associated with context.
2. If context's webgl context lost flag is set, abort these steps.
3. Set context's webgl context lost flag.
4. Invalidate all WebGLObject instances, such as textures and buffers, that have been created by this context (ie. is queries return false).
5. Queue a task to perform the following steps:
5.1. Fire a WebGL context event named "webglcontextlost" at canvas, with its statusMessage attribute set to "".
5.2. If the event's canceled flag is not set, abort these steps.
5.3. Perform the following steps asynchronously.
5.4. Await a restorable drawing buffer.
5.5. Restore the drawing buffer.

When the user agent is to restore the drawing buffer, it must queue a task to run the following steps:

1. Let canvas be the canvas object associated with the WebGLRenderingContext.
2. If canvas's webgl context lost flag is not set, abort these steps.
3. Create a drawing buffer using the settings specified in context's context creation parameters, and associate the drawing buffer with context, discarding any previous drawing buffer.
4. Clear canvas's webgl context lost flag.
5. Fire a WebGL context event named "webglcontextrestored" at canvas, with its statusMessage attribute set to "".

These definitions sound very good.
 

(cut here)

Notes:

Formatting above roughly emulates the rendering of HTML specs, highlighting flags, variables, types and algorithms.  Algorithms should be links (either to the algorithm, or to a normative reference); they're not actually italicized in HTML specs.

Using abstract flags like webgl context lost flag allows being much more precise about its side-effects.  Instead of these algorithms needing to monkey-patch things which are defined elsewhere ("now that the context is lost, these things happen..."), the definitions for the things affected by the flag simply use it directly.  This way, each function's definition isn't scattered around in a bunch of different places.  This removes eg. "isContextLost returns true"; instead, isContextLost's definition would say "Return true if webgl context lost flag is set, otherwise return false."

This sounds good -- a nice cleanup.
 
  If you don't want to adjust every call spec to handle the "are no-ops" and "return null" cases (that would be precise but tedious), then perhaps the beginning of 5.13 would be an appropriate place to put those.

Step 4 ("invalidate...") is loose.  It would be more precise to set a flag on each object (eg. a lost object flag), and (as above) where queries, etc. are defined, say "if the lost object flag is set, return false; otherwise...".

This raises an excellent point; the current text around invalidating WebGLObjects (in the definition of the webglcontextrestored event) is really underspecified. As you suggest above, I'd really like to centralize the definition of invalidation of these objects, because modifying the spec of every entry point taking a WebGLObject to handle context loss will be hard to maintain. Perhaps we could create a separate paragraph or sequence of steps about invalidation of objects, refer to it, and expand it as needed.

I've used "drawing buffer" to refer to the underlying OpenGL context, to avoid using the word "context" for multiple things.  (HTML specs regularly do this, intentionally using different terms to make separate concepts easier to distinguish.)

Canceled flag is defined in DOM4.  http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#events
Return a new object for contextId is defined in HTML. http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#getcontext-return

The events here aren't actually "fire a simple event", since it uses the WebGLContextEvent interface.  I've defined "fire a WebGL context event" for this.  This also fixes WebGLContextEvent not actually being used.  The language comes from DOM4.

The "interrupting" nature of losing a context is something that most web APIs are very careful to never allow.  Since it's (practically) unavoidable here, careful attention should be given to what its visible effects are.  I havn't yet done this.  Setting webgl context lost flag, and "invalidating instances", should happen atomically from the perspective of _javascript_ code.  There may be no language in HTML specs to copy for this, since other APIs never do this.  It should appear to the caller as if we take a lock at step 2 (of context loss), release it after step 4, and all other WebGL entry points hold that lock.  I mention this now, but let's iron out the simpler parts first.

Per your and Gregg's later comments, more precisely identifying when context loss can happen sounds good.
 

Context creation parameters are another missing detail.  This should probably be specified as a WebIDL dictionary, in the way that Event initializers are, and a copy should be stored to prevent it from being changed by the caller later.  We can come back to that later, too.

Yes, let's defer this. WebGLContextAttributes was specified as [Callback] so that a native object can be passed during context creation, and section 2.1 defines what getContextAttributes returns. It would be good to bring the specification in line with how other DOM specs are currently written, though.


(There are probably more details, but this has gone too long as is so I'll stop here for discussion.)

What would you think about creating a copy of the spec in the Subversion repository to which we can apply your edits and see how they look? I don't know how easy or difficult it would be to get you write access, but Gregg, I or others can help check in your changes as they evolve.

-Ken

 


--
Glenn Maynard