Files
gods-eye-view/src/standalone/rendererCache.js
T

86 lines
2.2 KiB
JavaScript

// This cache owns the parked renderer and its map. The layer session owns
// feeds, selection, media and the Director across both renderer attachments.
export function createRendererCache() {
const idle = new Map();
let retainKind;
async function acquire(kind, build, defer) {
const host = document.getElementById('cesiumContainer');
let entry = idle.get(kind);
idle.delete(kind);
if (entry?.lost) {
entry.dispose();
entry = null;
}
if (!entry) {
const container = document.createElement('div');
container.className = 'globe-renderer';
host.prepend(container);
const cleanups = [() => container.remove()];
const dispose = () => {
const errors = [];
while (cleanups.length) {
try {
cleanups.pop()();
} catch (error) {
errors.push(error);
}
}
if (errors.length)
throw new AggregateError(errors, 'Renderer cleanup failed');
};
try {
const scene = await build({
container,
defer: (fn) => cleanups.push(fn),
});
entry = { container, scene, dispose, lost: false };
scene.engine.host.canvas.addEventListener(
'webglcontextlost',
() => {
entry.lost = true;
},
{ once: true },
);
} catch (error) {
dispose();
throw error;
}
} else {
try {
host.prepend(entry.container);
entry.scene.resume();
entry.scene.engine.render.request('engine-resume');
} catch (error) {
entry.dispose();
throw error;
}
}
defer(() => {
const keep = retainKind === kind && !entry.lost;
retainKind = null;
if (!keep) return entry.dispose();
try {
entry.scene.suspend();
} catch (error) {
entry.dispose();
throw error;
}
entry.container.remove();
idle.set(kind, entry);
});
return entry.scene;
}
return {
acquire,
retain(kind) {
retainKind = kind;
},
clear() {
for (const entry of idle.values()) entry.dispose();
idle.clear();
},
};
}