Signatur
Beschreibung
loseContext() ist eine Methode der Erweiterung WEBGL_lose_context. Sie versetzt einen WebGLRenderingContext oder WebGL2RenderingContext künstlich in den Zustand „Kontext verloren“. Echte Kontextverluste kommen in der Praxis vor, etwa bei einem Absturz des GPU-Treibers, wenn das Betriebssystem den Grafikspeicher freigibt oder wenn der Browser bei zu vielen aktiven Kontexten alte Kontexte schließt. Mit dieser Methode lässt sich dieser Fall zuverlässig nachstellen.
Nach dem Aufruf löst das Canvas das Ereignis webglcontextlost aus. Alle WebGL-Ressourcen werden ungültig, also Texturen, Buffer, Shader, Programme und Framebuffer. gl.isContextLost() liefert dann true. Nur wenn im Handler von webglcontextlost die Methode event.preventDefault() aufgerufen wurde, kann der Kontext später wiederhergestellt werden. Das geschieht mit restoreContext() und löst das Ereignis webglcontextrestored aus.
Typische Einsatzgebiete:
- Automatisierte Tests der Wiederherstellungslogik: Ressourcen neu anlegen und die Render-Schleife neu starten.
- Gezieltes Freigeben der GPU-Ressourcen eines Canvas, das nicht mehr gebraucht wird, zum Beispiel beim Unmount einer Komponente in einer Single-Page-App.
Rückgabewert
webglcontextlost am Canvas gemeldet. Dieses Ereignis wird asynchron ausgelöst.Beispiele
Kontextverlust simulieren und wiederherstellen
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
const ext = gl.getExtension('WEBGL_lose_context');
canvas.addEventListener('webglcontextlost', (event) => {
event.preventDefault(); // nötig, damit eine Wiederherstellung möglich ist
console.log('Kontext verloren:', gl.isContextLost());
// Wiederherstellung nach einer Sekunde anstoßen
setTimeout(() => ext.restoreContext(), 1000);
});
canvas.addEventListener('webglcontextrestored', () => {
console.log('Kontext wiederhergestellt:', !gl.isContextLost());
// Hier alle Shader, Buffer und Texturen neu anlegen
});
ext.loseContext();
Wiederherstellungslogik einer Render-Schleife testen
const canvas = document.createElement('canvas');
document.body.append(canvas);
const gl = canvas.getContext('webgl2');
let frameId = null;
const initResources = () => {
// Shader kompilieren, Buffer anlegen usw.
gl.clearColor(0.1, 0.4, 0.8, 1);
};
const render = () => {
gl.clear(gl.COLOR_BUFFER_BIT);
frameId = requestAnimationFrame(render);
};
canvas.addEventListener('webglcontextlost', (e) => {
e.preventDefault();
cancelAnimationFrame(frameId);
console.log('Render-Schleife gestoppt');
});
canvas.addEventListener('webglcontextrestored', () => {
initResources();
render();
console.log('Render-Schleife neu gestartet');
});
initResources();
render();
// Testfall: Verlust erzwingen, danach wiederherstellen
const ext = gl.getExtension('WEBGL_lose_context');
ext?.loseContext();
setTimeout(() => ext?.restoreContext(), 500);
GPU-Ressourcen beim Entfernen eines Canvas freigeben
const destroyWebGLCanvas = (canvas) => {
const gl = canvas.getContext('webgl') ?? canvas.getContext('webgl2');
gl?.getExtension('WEBGL_lose_context')?.loseContext();
canvas.width = canvas.height = 1; // Speicher des Drawing-Buffers verkleinern
canvas.remove();
};
const canvas = document.querySelector('#preview');
destroyWebGLCanvas(canvas);
console.log('Canvas entfernt, Kontext freigegeben');
// Wichtig · Fallstricke
- Kein
preventDefault(), keine Wiederherstellung: Wirdevent.preventDefault()im Handler vonwebglcontextlostnicht aufgerufen, bleibt der Kontext dauerhaft verloren. Ein späteresrestoreContext()hat dann keine Wirkung. - Erweiterungsobjekt vorher speichern: Solange der Kontext verloren ist, liefert
getExtension()den Wertnull. Speichere das Objekt deshalb, bevor duloseContext()aufrufst. - Fehler bei doppeltem Aufruf: Ist der Kontext bereits verloren, erzeugt ein erneuter Aufruf von
loseContext()den WebGL-FehlerINVALID_OPERATION. Diesen Fehler kannst du mitgl.getError()abfragen. - Ressourcen neu anlegen: Alle WebGL-Objekte von vor dem Verlust sind danach ungültig. Nach
webglcontextrestoredmüssen Shader, Programme, Buffer und Texturen vollständig neu erzeugt werden. - Ereignisse kommen asynchron: Das Ereignis
webglcontextlostwird nicht synchron während des Aufrufs ausgelöst. - Kompatibilität: Die Erweiterung wird von allen modernen Browsern für WebGL 1 und WebGL 2 unterstützt. Prüfe trotzdem, ob
getExtension()ein Objekt zurückgibt, zum Beispiel mit optionaler Verkettung (?.).