// luma.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors const DEFAULT_CONTEXT_PROPS = { powerPreference: 'high-performance', // After all, most apps are using WebGL for performance reasons // eslint-disable-next-line no-console onContextLost: () => console.error('WebGL context lost'), // eslint-disable-next-line no-console onContextRestored: () => console.info('WebGL context restored') }; /** * Create a WebGL context for a canvas * Note calling this multiple time on the same canvas does return the same context * @param canvas A canvas element or offscreen canvas */ export function createBrowserContext(canvas, props) { props = { ...DEFAULT_CONTEXT_PROPS, ...props }; // Try to extract any extra information about why context creation failed let errorMessage = null; const onCreateError = error => (errorMessage = error.statusMessage || errorMessage); canvas.addEventListener('webglcontextcreationerror', onCreateError, false); // Create the desired context let gl = null; // props.failIfMajorPerformanceCaveat = true; // We require webgl2 context gl ||= canvas.getContext('webgl2', props); // Software GPU // props.failIfMajorPerformanceCaveat = false; // if (!gl && props.webgl1) { // gl = canvas.getContext('webgl', props); // } // TODO are we removing this listener before giving it a chance to fire? canvas.removeEventListener('webglcontextcreationerror', onCreateError, false); if (!gl) { throw new Error(`Failed to create WebGL context: ${errorMessage || 'Unknown error'}`); } if (props.onContextLost) { // Carefully extract and wrap callbacks to prevent addEventListener from rebinding them. const { onContextLost } = props; canvas.addEventListener('webglcontextlost', (event) => onContextLost(event), false); } if (props.onContextRestored) { // Carefully extract and wrap callbacks to prevent addEventListener from rebinding them. const { onContextRestored } = props; canvas.addEventListener('webglcontextrestored', (event) => onContextRestored(event), false); } return gl; } /* TODO - can we call this asynchronously to catch the error events? export async function createBrowserContextAsync(canvas: HTMLCanvasElement | OffscreenCanvas, props: ContextProps): Promise { props = {...DEFAULT_CONTEXT_PROPS, ...props}; // Try to extract any extra information about why context creation failed let errorMessage = null; const onCreateError = (error) => (errorMessage = error.statusMessage || errorMessage); canvas.addEventListener('webglcontextcreationerror', onCreateError, false); const gl = createBrowserContext(canvas, props); // Give the listener a chance to fire await new Promise(resolve => setTimeout(resolve, 0)); canvas.removeEventListener('webglcontextcreationerror', onCreateError, false); return gl; } */