Start · Sprachen · JavaScript · Referenz · WEBGL_lose_context.restoreContext()

WEBGL_lose_context.restoreContext()

Methode

Simuliert die Wiederherstellung eines zuvor per <code>loseContext()</code> verlorenen WebGL-Kontexts und löst das Ereignis <code>webglcontextrestored</code> aus.

seit JavaScript Baseline: alle modernen Browser (WebGL 1 und WebGL Kategorie: webapi

Signatur

WEBGL_lose_context.prototype.restoreContext()

Beschreibung

restoreContext() gehört zur WebGL-Erweiterung WEBGL_lose_context. Die Methode stellt einen Kontext wieder her, der vorher mit loseContext() künstlich verloren wurde. Danach löst der Browser auf dem <canvas> das Ereignis webglcontextrestored aus.

Die Methode ist vor allem ein Werkzeug zum Testen. In der Praxis kann ein WebGL-Kontext jederzeit verloren gehen, zum Beispiel durch einen Absturz des GPU-Treibers, durch Energiesparmodi auf Mobilgeräten oder weil zu viele Kontexte gleichzeitig offen sind. Mit loseContext() und restoreContext() lässt sich dieser Ablauf gezielt nachstellen. So prüfen Sie, ob Ihre Anwendung alle GPU-Ressourcen korrekt neu anlegt: Shader, Programme, Puffer, Texturen und Framebuffer.

Wichtig: Durch die Wiederherstellung wird kein alter Zustand zurückgebracht. Alle WebGL-Objekte, die vor dem Verlust existierten, sind ungültig. Der Handler für webglcontextrestored muss sie komplett neu erzeugen. Damit eine Wiederherstellung überhaupt möglich ist, muss außerdem im Handler für webglcontextlost die Methode event.preventDefault() aufgerufen werden.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Die Wiederherstellung läuft asynchron ab und wird über das Ereignis webglcontextrestored gemeldet.

Beispiele

Kontextverlust und Wiederherstellung simulieren

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
const ext = gl.getExtension('WEBGL_lose_context');

canvas.addEventListener('webglcontextlost', (event) => {
  event.preventDefault(); // Voraussetzung für die Wiederherstellung
  console.log('Kontext verloren:', gl.isContextLost());
});

canvas.addEventListener('webglcontextrestored', () => {
  console.log('Kontext wiederhergestellt:', !gl.isContextLost());
});

ext.loseContext();
// Kurz warten, dann wiederherstellen
setTimeout(() => ext.restoreContext(), 1000);
Kontext verloren: true Kontext wiederhergestellt: true

Ressourcen nach der Wiederherstellung neu anlegen

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');
let program = null;
let buffer = null;

const initResources = () => {
  const vs = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vs, 'attribute vec2 p; void main(){ gl_Position = vec4(p, 0.0, 1.0); }');
  gl.compileShader(vs);
  const fs = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fs, 'precision mediump float; void main(){ gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0); }');
  gl.compileShader(fs);
  program = gl.createProgram();
  gl.attachShader(program, vs);
  gl.attachShader(program, fs);
  gl.linkProgram(program);

  buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.8, -0.8, -0.8, 0.8, -0.8]), gl.STATIC_DRAW);
};

const draw = () => {
  if (gl.isContextLost()) return;
  gl.clearColor(0, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.useProgram(program);
  const loc = gl.getAttribLocation(program, 'p');
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.enableVertexAttribArray(loc);
  gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
  gl.drawArrays(gl.TRIANGLES, 0, 3);
};

canvas.addEventListener('webglcontextlost', (e) => e.preventDefault());
canvas.addEventListener('webglcontextrestored', () => {
  initResources(); // alte Objekte sind ungültig
  draw();
  console.log('Szene neu aufgebaut');
});

initResources();
draw();
Szene neu aufgebaut (nach restoreContext())

Testhilfe als Promise-basierte Funktion

const simulateContextLoss = (canvas, gl) => new Promise((resolve, reject) => {
  const ext = gl.getExtension('WEBGL_lose_context');
  if (!ext) return reject(new Error('WEBGL_lose_context nicht verfügbar'));

  canvas.addEventListener('webglcontextlost', (e) => {
    e.preventDefault();
    ext.restoreContext();
  }, { once: true });

  canvas.addEventListener('webglcontextrestored', () => resolve(), { once: true });
  ext.loseContext();
});

const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2');
await simulateContextLoss(canvas, gl);
console.log('Test bestanden, Kontext aktiv:', !gl.isContextLost());
Test bestanden, Kontext aktiv: true

// Wichtig · Fallstricke

  • Nur nach loseContext(): Ist der Kontext nicht verloren, erzeugt restoreContext() den Fehler INVALID_OPERATION (abrufbar über gl.getError()). Das gilt auch, wenn der Verlust nicht durch die Erweiterung simuliert wurde.
  • preventDefault() ist Pflicht: Rufen Sie event.preventDefault() im Handler für webglcontextlost nicht auf, wird der Kontext nie wiederhergestellt.
  • Asynchron: Die Wiederherstellung ist nicht sofort abgeschlossen, wenn der Aufruf zurückkehrt. Zeichnen Sie erst im Handler für webglcontextrestored wieder.
  • Kein Zustand bleibt erhalten: Alle alten WebGLBuffer-, WebGLTexture-, WebGLProgram- und weiteren Objekte sind ungültig. Auch Erweiterungen müssen mit getExtension() neu angefordert werden. Das Erweiterungsobjekt WEBGL_lose_context selbst bleibt benutzbar.
  • Kompatibilität: Die Methode wird von allen modernen Browsern unterstützt, sowohl mit WebGL 1 als auch mit WebGL 2. Prüfen Sie trotzdem immer, ob getExtension() nicht null zurückgibt.
  • Gedacht für Tests und Fehlersuche. Im Produktivcode sollten Sie echten Kontextverlust nicht auslösen, aber immer darauf reagieren können.