Improve context lost handling

This commit is contained in:
schmelczerandras 2020-11-09 11:53:43 +01:00
parent 9d5c11543c
commit 77ade80753
4 changed files with 26 additions and 21 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "sdf-2d", "name": "sdf-2d",
"version": "0.7.1", "version": "0.7.2",
"description": "Graphics framework for efficiently rendering 2D signed distance fields.", "description": "Graphics framework for efficiently rendering 2D signed distance fields.",
"keywords": [ "keywords": [
"webgl", "webgl",

View file

@ -0,0 +1,4 @@
/**
* @internal
*/
export class ContextLostException {}

View file

@ -1,4 +1,5 @@
import { RendererInfo } from '../rendering/renderer/renderer-info'; import { RendererInfo } from '../rendering/renderer/renderer-info';
import { ContextLostException } from './context-lost-exception';
/** @internal */ /** @internal */
export type UniversalRenderingContext = ( export type UniversalRenderingContext = (
@ -70,7 +71,7 @@ export const getUniversalRenderingContext = (
if (typeof value === 'function') { if (typeof value === 'function') {
if (isDestroyed || target.isContextLost()) { if (isDestroyed || target.isContextLost()) {
isDestroyed = true; isDestroyed = true;
throw new Error('Context lost'); throw new ContextLostException();
} }
return value.bind(target); return value.bind(target);

View file

@ -2,6 +2,7 @@ import { ReadonlyVec2, vec2 } from 'gl-matrix';
import { Drawable } from '../../../drawables/drawable'; import { Drawable } from '../../../drawables/drawable';
import { DrawableDescriptor } from '../../../drawables/drawable-descriptor'; import { DrawableDescriptor } from '../../../drawables/drawable-descriptor';
import { formatLog } from '../../../helper/format-log'; import { formatLog } from '../../../helper/format-log';
import { ContextLostException } from '../../graphics-library/context-lost-exception';
import { RuntimeSettings } from '../settings/runtime-settings'; import { RuntimeSettings } from '../settings/runtime-settings';
import { StartupSettings } from '../settings/startup-settings'; import { StartupSettings } from '../settings/startup-settings';
import { Renderer } from './renderer'; import { Renderer } from './renderer';
@ -40,31 +41,27 @@ export class ContextAwareRenderer implements Renderer {
} }
private createRenderer() { private createRenderer() {
try { this.renderer = new RendererImplementation(
this.renderer = new RendererImplementation( this.canvas,
this.canvas, this.descriptors,
this.descriptors, this.ignoreWebGL2
this.ignoreWebGL2 );
); this.readyPromise = this.renderer.initialize(this.settingsOverrides);
this.readyPromise = this.renderer.initialize(this.settingsOverrides); this.waitForRenderer();
this.waitForRenderer();
} catch (e) {
if (!e.message.includes('Context lost')) {
throw e;
}
}
} }
private async waitForRenderer() { private async waitForRenderer() {
try { try {
await this.readyPromise; await this.readyPromise;
this.isRendererReady = true;
} catch (e) { } catch (e) {
if (!e.message.includes('Context lost')) { if (e instanceof ContextLostException) {
throw e; this.createRenderer();
return;
} }
throw e;
} }
this.isRendererReady = true;
this.setRuntimeSettings(this.runtimeOverrides); this.setRuntimeSettings(this.runtimeOverrides);
if (this.previousViewAreaTopLeft && this.previousViewAreaSize) { if (this.previousViewAreaTopLeft && this.previousViewAreaSize) {
this.setViewArea(this.previousViewAreaTopLeft, this.previousViewAreaSize); this.setViewArea(this.previousViewAreaTopLeft, this.previousViewAreaSize);
@ -88,7 +85,7 @@ export class ContextAwareRenderer implements Renderer {
try { try {
return f(); return f();
} catch (e) { } catch (e) {
if (e.message.includes('Context lost')) { if (e instanceof ContextLostException) {
this.isRendererReady = false; this.isRendererReady = false;
return defaultValue; return defaultValue;
} }
@ -100,11 +97,14 @@ export class ContextAwareRenderer implements Renderer {
} }
public get canvasSize(): ReadonlyVec2 { public get canvasSize(): ReadonlyVec2 {
return this.handle(() => this.renderer.canvasSize, vec2.create()); return this.handle(() => this.renderer.canvasSize, vec2.fromValues(1, 1));
} }
public get viewAreaSize(): ReadonlyVec2 { public get viewAreaSize(): ReadonlyVec2 {
return this.handle(() => this.renderer.viewAreaSize, vec2.create()); return this.handle(
() => this.renderer.viewAreaSize,
this.previousViewAreaSize ?? vec2.fromValues(1, 1)
);
} }
public get insights(): RendererInfo | null { public get insights(): RendererInfo | null {