mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
Read a parked globe's WebGL context from the one it was built with instead of asking its canvas during a switch
Asking the canvas again during the switch made the reuse depend on getContext at that moment: with new contexts refused (qa-strict-failure-matrix, cold Navara to Cesium) the rollback to the parked Navara threw and left no globe.
This commit is contained in:
1 parent
90d64e6916
commit
726e201314
2 files changed
+25
-8
No files matched your search
@@ -9,11 +9,8 @@ export function createRendererCache() {
|
|||||||
let entry = idle.get(kind);
|
let entry = idle.get(kind);
|
||||||
idle.delete(kind);
|
idle.delete(kind);
|
||||||
// loseContext() takes effect before its queued DOM event is delivered.
|
// loseContext() takes effect before its queued DOM event is delivered.
|
||||||
// Check the existing context too, before resuming a parked render loop.
|
// Check the context itself too, before resuming a parked render loop.
|
||||||
const canvas = entry?.scene.engine.host.canvas;
|
if (entry && (entry.lost || entry.context?.isContextLost?.())) {
|
||||||
const context =
|
|
||||||
canvas?.getContext?.('webgl2') ?? canvas?.getContext?.('webgl');
|
|
||||||
if (entry && (entry.lost || context?.isContextLost())) {
|
|
||||||
entry.dispose();
|
entry.dispose();
|
||||||
entry = null;
|
entry = null;
|
||||||
}
|
}
|
||||||
@@ -39,7 +36,13 @@ export function createRendererCache() {
|
|||||||
container,
|
container,
|
||||||
defer: (fn) => cleanups.push(fn),
|
defer: (fn) => cleanups.push(fn),
|
||||||
});
|
});
|
||||||
entry = { container, scene, dispose, lost: false };
|
// The context the globe draws with, read once while it is new: a
|
||||||
|
// switch reads its state and never asks the canvas again (a canvas
|
||||||
|
// asked for another context type would create one).
|
||||||
|
const canvas = scene.engine.host.canvas;
|
||||||
|
const context =
|
||||||
|
canvas.getContext?.('webgl2') ?? canvas.getContext?.('webgl') ?? null;
|
||||||
|
entry = { container, scene, dispose, lost: false, context };
|
||||||
scene.engine.host.canvas.addEventListener(
|
scene.engine.host.canvas.addEventListener(
|
||||||
'webglcontextlost',
|
'webglcontextlost',
|
||||||
() => {
|
() => {
|
||||||
|
|||||||
@@ -27,7 +27,11 @@ test('a parked renderer is reused, but a lost context is disposed before rebuild
|
|||||||
defer(() => {
|
defer(() => {
|
||||||
released += 1;
|
released += 1;
|
||||||
});
|
});
|
||||||
|
const canvas = new EventTarget();
|
||||||
|
const context = { lost: false, isContextLost: () => context.lost };
|
||||||
|
canvas.getContext = (type) => (type === 'webgl2' ? context : null);
|
||||||
return {
|
return {
|
||||||
|
context,
|
||||||
suspend() {
|
suspend() {
|
||||||
this.running = false;
|
this.running = false;
|
||||||
},
|
},
|
||||||
@@ -35,7 +39,7 @@ test('a parked renderer is reused, but a lost context is disposed before rebuild
|
|||||||
this.running = true;
|
this.running = true;
|
||||||
},
|
},
|
||||||
engine: {
|
engine: {
|
||||||
host: { container, canvas: new EventTarget() },
|
host: { container, canvas },
|
||||||
render: { request() {} },
|
render: { request() {} },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -49,13 +53,23 @@ test('a parked renderer is reused, but a lost context is disposed before rebuild
|
|||||||
release();
|
release();
|
||||||
assert.equal(first.running, false);
|
assert.equal(first.running, false);
|
||||||
assert.equal(first.engine.host.container.isConnected, false);
|
assert.equal(first.engine.host.container.isConnected, false);
|
||||||
|
// A parked renderer whose canvas no longer hands out contexts is still
|
||||||
|
// reused when its own context is alive.
|
||||||
|
first.engine.host.canvas.getContext = () => {
|
||||||
|
throw new Error('getContext called during a switch');
|
||||||
|
};
|
||||||
assert.equal(await open(), first);
|
assert.equal(await open(), first);
|
||||||
assert.equal(first.running, true);
|
assert.equal(first.running, true);
|
||||||
assert.equal(first.engine.host.container.isConnected, true);
|
assert.equal(first.engine.host.container.isConnected, true);
|
||||||
cache.retain('navara');
|
cache.retain('navara');
|
||||||
release();
|
release();
|
||||||
// The WebGL context is already lost, but its DOM event has not fired.
|
// The WebGL context is already lost, but its DOM event has not fired.
|
||||||
first.engine.host.canvas.getContext = () => ({ isContextLost: () => true });
|
// The switch reads the context the globe was built with and never asks
|
||||||
|
// the canvas again (a QA or driver failure of getContext must not decide).
|
||||||
|
first.context.lost = true;
|
||||||
|
first.engine.host.canvas.getContext = () => {
|
||||||
|
throw new Error('getContext called during a switch');
|
||||||
|
};
|
||||||
const second = await open();
|
const second = await open();
|
||||||
assert.notEqual(second, first);
|
assert.notEqual(second, first);
|
||||||
assert.equal(released, 1);
|
assert.equal(released, 1);
|
||||||
|
|||||||
Reference in new issue
Block a user