mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-06-29 03:30:52 +00:00
### 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.
114 lines
3.5 KiB
TypeScript
114 lines
3.5 KiB
TypeScript
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
import {Logger} from '../../instrument';
|
|
|
|
import {WebGLContext} from './webgl-context';
|
|
|
|
const cache: {[contextId: string]: WebGLContext} = {};
|
|
|
|
/**
|
|
* This factory function creates proper WebGLRenderingContext based on
|
|
* the current browsers capabilities
|
|
* The order is from higher/most recent versions to most basic
|
|
*/
|
|
export function createWebGLContext(contextId?: 'webgl'|'webgl2'): WebGLContext {
|
|
let context: WebGLContext|undefined;
|
|
if ((!contextId || contextId === 'webgl2') && 'webgl2' in cache) {
|
|
context = cache.webgl2;
|
|
} else if ((!contextId || contextId === 'webgl') && 'webgl' in cache) {
|
|
context = cache.webgl;
|
|
}
|
|
|
|
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;
|
|
|
|
cache[contextId] = context;
|
|
|
|
if (gl.isContextLost()) {
|
|
delete cache[contextId];
|
|
return createWebGLContext(contextId);
|
|
}
|
|
|
|
gl.disable(gl.DEPTH_TEST);
|
|
gl.disable(gl.STENCIL_TEST);
|
|
gl.disable(gl.BLEND);
|
|
gl.disable(gl.DITHER);
|
|
gl.disable(gl.POLYGON_OFFSET_FILL);
|
|
gl.disable(gl.SAMPLE_COVERAGE);
|
|
gl.enable(gl.SCISSOR_TEST);
|
|
gl.enable(gl.CULL_FACE);
|
|
gl.cullFace(gl.BACK);
|
|
|
|
return context;
|
|
}
|
|
|
|
export function createNewWebGLContext(canvas: HTMLCanvasElement, contextId?: 'webgl'|'webgl2'): WebGLContext {
|
|
const contextAttributes: WebGLContextAttributes = {
|
|
alpha: false,
|
|
depth: false,
|
|
antialias: false,
|
|
stencil: false,
|
|
preserveDrawingBuffer: false,
|
|
premultipliedAlpha: false,
|
|
failIfMajorPerformanceCaveat: false
|
|
};
|
|
let gl: WebGLRenderingContext|null;
|
|
const ca = contextAttributes;
|
|
if (!contextId || contextId === 'webgl2') {
|
|
gl = canvas.getContext('webgl2', ca);
|
|
if (gl) {
|
|
try {
|
|
return new WebGLContext(gl, 2);
|
|
} catch (err) {
|
|
Logger.warning('GlContextFactory', `failed to create WebGLContext using contextId 'webgl2'. Error: ${err}`);
|
|
}
|
|
}
|
|
}
|
|
if (!contextId || contextId === 'webgl') {
|
|
gl = canvas.getContext('webgl', ca) || canvas.getContext('experimental-webgl', ca) as WebGLRenderingContext;
|
|
if (gl) {
|
|
try {
|
|
return new WebGLContext(gl, 1);
|
|
} catch (err) {
|
|
Logger.warning(
|
|
'GlContextFactory',
|
|
`failed to create WebGLContext using contextId 'webgl' or 'experimental-webgl'. Error: ${err}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
throw new Error('WebGL is not supported');
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
declare let OffscreenCanvas: {new (width: number, height: number): HTMLCanvasElement};
|
|
|
|
function createCanvas(): HTMLCanvasElement {
|
|
if (typeof document === 'undefined') {
|
|
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);
|
|
}
|