Skip to content

Commit ec63228

Browse files
committed
Recover from webgl context loss
On mobile webgl gets stopped when not used if memory is low. But can be restored. Part of #639 AI use: Sonnet 4.6 to research best practices. Interactives session to implement and review.
1 parent e0dfce4 commit ec63228

3 files changed

Lines changed: 51 additions & 3 deletions

File tree

flock.js

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ export const flock = {
137137
canvas: null,
138138
abortController: null,
139139
_renderLoop: null,
140+
_contextLostAt: null,
141+
_escalationTimer: null,
142+
_webglVisibilityListenerAdded: false,
140143
document: document,
141144
disposed: null,
142145
events: {},
@@ -1329,6 +1332,18 @@ export const flock = {
13291332
}
13301333
});
13311334
},
1335+
_scheduleContextEscalation() {
1336+
clearTimeout(flock._escalationTimer);
1337+
flock._escalationTimer = setTimeout(() => {
1338+
flock._escalationTimer = null;
1339+
if (flock.engine?.isContextLost?.()) {
1340+
handleError(new Error('WebGL context restore timeout'), {
1341+
source: 'webgl-lost',
1342+
fatal: true,
1343+
});
1344+
}
1345+
}, 8000);
1346+
},
13321347
createEngine() {
13331348
flock.engine?.dispose();
13341349
flock.engine = null;
@@ -1341,13 +1356,44 @@ export const flock = {
13411356
lockstepMaxSteps: 4,
13421357
});
13431358

1359+
// Call preventDefault() on the raw event so the browser is willing to restore.
1360+
flock.canvas.addEventListener('webglcontextlost', (event) => {
1361+
event.preventDefault();
1362+
});
1363+
13441364
flock.engine.onContextLostObservable.add(() => {
1345-
handleError(new Error('WebGL context lost'), {
1346-
source: 'webgl-lost',
1347-
fatal: true,
1365+
flock._contextLostAt = Date.now();
1366+
showBanner('webgl-lost', {
1367+
message: translate('error_webgl_restoring'),
13481368
});
1369+
if (document.visibilityState === 'visible') {
1370+
flock._scheduleContextEscalation();
1371+
}
13491372
});
13501373

1374+
flock.engine.onContextRestoredObservable.add(() => {
1375+
clearTimeout(flock._escalationTimer);
1376+
flock._escalationTimer = null;
1377+
flock._contextLostAt = null;
1378+
dismissBanner('webgl-lost');
1379+
flock.engine.resize();
1380+
if (flock._renderLoop) {
1381+
flock.engine.runRenderLoop(flock._renderLoop);
1382+
}
1383+
});
1384+
1385+
if (!flock._webglVisibilityListenerAdded) {
1386+
flock._webglVisibilityListenerAdded = true;
1387+
document.addEventListener('visibilitychange', () => {
1388+
if (document.visibilityState === 'visible' && flock._contextLostAt) {
1389+
flock.engine?.resize();
1390+
if (!flock._escalationTimer) {
1391+
flock._scheduleContextEscalation();
1392+
}
1393+
}
1394+
});
1395+
}
1396+
13511397
flock.engine.enableOfflineSupport = false;
13521398
flock.engine.setHardwareScalingLevel(1 / window.devicePixelRatio);
13531399
},

locale/en.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,7 @@ export default {
11821182
error_startup: "Flock couldn't start up. Try reloading the page.",
11831183
error_project_crash:
11841184
"Your project hit a problem. Press Stop, check your blocks, then press Play again.",
1185+
error_webgl_restoring: "3D view paused, restoring…",
11851186
error_webgl_lost: "The 3D view stopped working. Try reloading the page.",
11861187
error_physics_oom:
11871188
"Your project ran out of memory. Try reloading the page and using fewer blocks.",

locale/es.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,7 @@ export default {
11831183
error_startup: "Flock no se pudo iniciar. Intenta recargar la página.", // human
11841184
error_project_crash:
11851185
"Tu proyecto tuvo un problema. Pulsa Detener, revisa tus bloques y pulsa Reproducir otra vez.", // human
1186+
error_webgl_restoring: "Vista 3D pausada, restaurando…", // human
11861187
error_webgl_lost:
11871188
"La vista 3D dejó de funcionar. Intenta recargar la página.", // human
11881189
error_physics_oom:

0 commit comments

Comments
 (0)