Try to handle GL context losses
authorRobert Kaiser <kairo@kairo.at>
Sun, 29 Jun 2014 23:30:35 +0000 (01:30 +0200)
committerRobert Kaiser <kairo@kairo.at>
Sun, 29 Jun 2014 23:30:35 +0000 (01:30 +0200)
js/map.js
js/ui.js
manifest.appcache

index cf095cb..ec9a05c 100644 (file)
--- a/js/map.js
+++ b/js/map.js
@@ -72,11 +72,19 @@ function initMap() {
               gGLMapCanvas.getContext("experimental-webgl", {depth: false});
   }
   catch(e) {}
-  // If we don't have a GL context, give up now
   if (!gMap.gl) {
+    // If we don't have a GL context, give up now
     showGLWarningDialog();
     gMap.gl = null;
   }
+  else {
+    // GL context can be lost at any time, handle that.
+    // See http://www.khronos.org/webgl/wiki/HandlingContextLost
+    gGLMapCanvas.addEventListener("webglcontextlost",
+                                  gMap.handleContextLost, false);
+    gGLMapCanvas.addEventListener("webglcontextrestored",
+                                  gMap.handleContextRestored, false);
+  }
   gTrackCanvas = document.getElementById("track");
   gTrackContext = gTrackCanvas.getContext("2d");
   if (!gMap.activeMap)
@@ -235,7 +243,7 @@ var gMap = {
     '  gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);\n' +
     '  vTextureCoord = aTextureCoord;\n' +
     '}'; },
-  getFragShaderSource:function() {
+  getFragShaderSource: function() {
     return 'varying highp vec2 vTextureCoord;\n\n' +
     'uniform sampler2D uImage;\n\n' +
     'void main(void) {\n' +
@@ -312,8 +320,13 @@ var gMap = {
       gMap.glTxCleanIntervalID = window.setInterval(gMap.cleanTextures, 30 * 1000);
     }
 
-    var throwEv = new CustomEvent("mapinit-done");
-    gAction.dispatchEvent(throwEv);
+    if (!gAppInitDone) {
+      // We may be called when context was lost and destroyed,
+      // only send event when we are in app startup
+      // (gAppInitDone is set to true right after we return this event).
+      var throwEv = new CustomEvent("mapinit-done");
+      gAction.dispatchEvent(throwEv);
+    }
   },
 
   draw: function() {
@@ -503,9 +516,21 @@ var gMap = {
         }
       }
       console.log("Cleaning complete, " + Object.keys(gMap.glTextures).length + " textures left)");
-      //clearInterval(gMap.glTxCleanIntervalID);
     }
   },
+
+  handleContextLost: function(event) {
+    event.preventDefault();
+    // GL context is gone, let's reset everything that depends on it.
+    clearInterval(gMap.glTxCleanIntervalID);
+    gMap.glTextures = {};
+  },
+
+  handleContextRestored: function(event) {
+    // When GL context is back, init GL again and draw.
+    gMap.initGL();
+    gMap.draw();
+  },
 }
 
 // Using scale(x, y) together with drawing old data on scaled canvas would be an improvement for zooming.
index 7f0afd5..0e0650f 100644 (file)
--- a/js/ui.js
+++ b/js/ui.js
@@ -7,6 +7,7 @@ window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndex
 window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
 
 var mainDB;
+var gAppInitDone = false;
 var gUIHideCountdown = 0;
 var gWaitCounter = 0;
 var gAction, gActionLabel;
@@ -66,6 +67,7 @@ function postInit(aEvent) {
   gAction.removeEventListener(aEvent.type, postInit, false);
   console.log("init done, draw map.");
   gMapPrefsLoaded = true;
+  gAppInitDone = true;
   //gMap.resizeAndDraw();  <-- HACK: This triggers bug 1001853, work around with a delay.
   window.setTimeout(gMap.resizeAndDraw, 100);
   gActionLabel.textContent = "";
index 1133f56..3cbe3f0 100644 (file)
@@ -1,6 +1,7 @@
 CACHE MANIFEST
 
-# 2014-05-12
+# 2014-06-29
+index.html
 manifest.webapp
 js/map.js
 js/ui.js