[js/web] update webgl context creating (#16436)

### Description
Modify the creating of webgl context.

Previous behavior:
STEP.1 - create canvas (document.createElement), if failed, goto step.2
else step.3
STEP.2 - create offscreenCanvas, if failed abort
STEP.3 - use the canvas created in step.1 or 2 to create webgl context.
if successful return context else abort

Now bahavior:
STEP.1 create offscreenCanvas, if failed goto step.3
STEP.2 use it to create webgl context. if successful, return context
STEP.3 create canvas  (document.createElement). if failed, abort
STEP.4 use it to create webgl context. if successful, return context
else abort

Motivation:
we found in some environment, normalCanvas.getContext() returns null but
offscreenCanvas.getContext() returns the context object. and when
offscreenCanvas is available it is good idea to always prefer to use it.
This commit is contained in:
Yulong Wang 2023-06-21 17:10:26 -07:00 committed by GitHub
parent 3c2d52a995
commit de476c8075
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -20,7 +20,18 @@ export function createWebGLContext(contextId?: 'webgl'|'webgl2'): WebGLContext {
context = cache.webgl;
}
context = context || createNewWebGLContext(contextId);
if (!context) {
try {
// try to create webgl context from an offscreen canvas
const offscreenCanvas = createOffscreenCanvas();
context = createNewWebGLContext(offscreenCanvas, contextId);
} catch (e) {
// if failed, fallback to try to use a normal canvas element
const canvas = createCanvas();
context = createNewWebGLContext(canvas, contextId);
}
}
contextId = contextId || context.version === 1 ? 'webgl' : 'webgl2';
const gl = context.gl;
@ -44,8 +55,7 @@ export function createWebGLContext(contextId?: 'webgl'|'webgl2'): WebGLContext {
return context;
}
export function createNewWebGLContext(contextId?: 'webgl'|'webgl2'): WebGLContext {
const canvas = createCanvas();
export function createNewWebGLContext(canvas: HTMLCanvasElement, contextId?: 'webgl'|'webgl2'): WebGLContext {
const contextAttributes: WebGLContextAttributes = {
alpha: false,
depth: false,
@ -88,13 +98,17 @@ declare let OffscreenCanvas: {new (width: number, height: number): HTMLCanvasEle
function createCanvas(): HTMLCanvasElement {
if (typeof document === 'undefined') {
if (typeof OffscreenCanvas === 'undefined') {
throw new TypeError('failed to create canvas: OffscreenCanvas is not supported');
}
return new OffscreenCanvas(1, 1);
throw new TypeError('failed to create canvas: document is not supported');
}
const canvas: HTMLCanvasElement = document.createElement('canvas');
canvas.width = 1;
canvas.height = 1;
return canvas;
}
function createOffscreenCanvas(): HTMLCanvasElement {
if (typeof OffscreenCanvas === 'undefined') {
throw new TypeError('failed to create offscreen canvas: OffscreenCanvas is not supported');
}
return new OffscreenCanvas(1, 1);
}