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

Re: [Public WebGL] Addition to WebGLContextLostEvent wrt extensions





On Wed, Apr 7, 2010 at 12:07 AM, Cedric Vivier <cedricv@neonux.com> wrote:
On Tue, Apr 6, 2010 at 23:42, Gregg Tavares <gman@google.com> wrote:
On Tue, Apr 6, 2010 at 7:03 PM, Cedric Vivier <cedricv@neonux.com> wrote:
I don't think this is an issue at all in WebGL due to the simple single-threaded event model of _javascript_.
Afaik contrary to C-like signals which are preemptive, once the loop is started it will have to finish before _javascript_ can handle any WebGLContextLostEvent or WebGLContextRestored event.
If the context is lost at 120, the loop will continue and quickly generate GL errors at every subsequent call until it stops; then when the current _javascript_ chunk has been completed the registered WebGLContextLostEvent handler will be ran then the WebGLContextRestored handler, which will likely restart the whole loop again (assuming this loop is in e.g init).


The WebGLContextLostEvent and WebGLContextRestored event may be single threaded but GL itself is not. The user can press the hibernate button at any time.  If the model is WebGL restores its self which is what WebGLContextRestored suggests that this is a real case. I can keep trying to come up with examples where the context going from bad to good without app control is bad idea.
 

I was assuming it would be possible for WebGL implementations to restore the context ONLY just before the _javascript_ handler is executed (e.g an internal native event listener that resets the context when the dispatched event is actually ready for execution in the _javascript_ context).
Afaik *if that's possible* (?) then WebGLContextRestored would have no drawbacks but only advantages (simplicity in both concept and user code implementation) compared with a WebGLContextReady+resetContext() right? (since the order of execution would be obligatory the same in both cases)

Maybe some sample code would help me see how WebGLContextRestored would work.

Here's some code that might show where I see an issue. Maybe this is just bad code.

var loadCount = 1;
var texturesToLoad = [
  "tree.png",
  "brick.png",
  "player.png"
];

var texturesByName = {};

function init() {
  for (var ii = 0; ii < texturesToLoad.length; ++ii) {
    ++loadCount;
    var img = new document.createElement("img");
    img. texturesToLoad[ii]);
    img.src = "">

    function createOnLoadFunction(img, name) {
       return function() {
          var tex = ctx.createTexture();
          ctx.bindTexture(ctx.TEXTURE_2D, tex);
          ctx.texImage2D(ctx.TEXTURE_2D, 0, img);
          texturesByName[name] = tex;
          checkForAllTexturesLoaded();
       }
    }
 
    function checkForAllTexturesLoaded() {
      --loadCount;
      if (loadCount == 0) {
         startApp();
      }
    }
  }
}
 
function startApp() {
   // code after initialization
}

I'm not sure how I'm supposed to recover from that with WebGLContextRestored. Things are loading in the background, I have no idea what order images will get loaded so I'd have to some how keep a flag on each image, whether it's been loaded or not and then if I get WebGLContextLost cancel all images that haven't loaded yet because I don't want them to create textures if I happen to get WebGLContextRestored after a WebGLContextLost

If on the other hand I have WebGLContextResetable/ctx.reset then I know that once I get WebGLContextLost, everything I do after that is bad and only I get to choose when it's good again.

g_contextLost = false;
g_contextResetable = false;

canvas.addEventListener("webglcontextlost", contextLostHandler, false);
canvas.addEventListener("webglcontextrestable", contextResetableHandler, false);

function contextLostHandler() {
  g_contextLost = true;
}

function contextResetableHandler() {
  g_contextResetable = true;
  checkForAppRestart();
}

function startApp() {
  if (g_contextLost) {
    restartApp();
    return;

  }

  // do normal stuff.
}

function checkForAppRestart() {
  if (g_contextReady && g_shouldRestart) {
    g_shoudlRestart = false;
    g_contextResetable = false;
    ctx.reset();
    init();
  }
}

function restartApp() {
    g_shouldRestart = true;
    checkForAppRestart();
}


Wow, that was some pretty convoluted logic there.   Seriously, an example using the WebGLContextRestored would be great in working this out.  I can think of some ways of using it but they seem far off from the normal GL practices. With reset, the code above may look convoluted but really it's almost all boilerplate.  I just take my old GL app and wrap that ugly context lost handling code around my init and start.