import { PAGModule } from '../pag-module'; import { WEBGL_CONTEXT_ATTRIBUTES } from '../constant'; import { isInstanceOf } from '../utils/type-utils'; export class BackendContext { public static from(gl: WebGLRenderingContext | WebGL2RenderingContext | BackendContext): BackendContext { if (gl instanceof BackendContext) { return new BackendContext(gl.handle, true); } else { const majorVersion = isInstanceOf(gl, globalThis.WebGL2RenderingContext) ? 2 : 1; const { GL } = PAGModule; let id = 0; if (GL.contexts.length > 0) { id = GL.contexts.findIndex((context) => context?.GLctx === gl); } if (id < 1) { id = GL.registerContext(gl, { majorVersion: majorVersion, minorVersion: 0, ...WEBGL_CONTEXT_ATTRIBUTES, }); return new BackendContext(id); } return new BackendContext(id, true); } } public handle: number; private externallyOwned: boolean; private isDestroyed = false; private oldHandle = 0; public constructor(handle: number, externallyOwned = false) { this.handle = handle; this.externallyOwned = externallyOwned; } public getContext(): WebGLRenderingContext | null { return PAGModule.GL.getContext(this.handle)!.GLctx; } public makeCurrent(): boolean { if (this.isDestroyed) return false; this.oldHandle = PAGModule.GL.currentContext?.handle || 0; if (this.oldHandle === this.handle) return true; return PAGModule.GL.makeContextCurrent(this.handle); } public clearCurrent() { if (this.isDestroyed) return; if (this.oldHandle === this.handle) return; PAGModule.GL.makeContextCurrent(0); if (this.oldHandle) { PAGModule.GL.makeContextCurrent(this.oldHandle); } } /** * Register WebGLTexture in EmscriptenGL, And return handle. */ public registerTexture(texture: WebGLTexture) { return this.register(PAGModule.GL.textures, texture); } /** * Get WebGLTexture by handle. */ public getTexture(handled: number): WebGLTexture | null { return PAGModule.GL.textures[handled]; } /** * Unregister WebGLTexture reference in EmscriptenGL. */ public unregisterTexture(handle: number) { PAGModule.GL.textures[handle] = null; } /** * Register WebGLFramebuffer in EmscriptenGL, And return handle. */ public registerRenderTarget(framebuffer: WebGLFramebuffer) { return this.register(PAGModule.GL.framebuffers, framebuffer); } /** * Get WebGLFramebuffer by handle. */ public getRenderTarget(handle: number): WebGLFramebuffer | null { return PAGModule.GL.framebuffers[handle]; } /** * Unregister WebGLTexture reference in EmscriptenGL. */ public unregisterRenderTarget(handle: number) { PAGModule.GL.framebuffers[handle] = null; } public destroy(): void { if (this.externallyOwned) { return; } PAGModule.GL.deleteContext(this.handle); } private register(table: (T | null)[], item: T): number { const handle = PAGModule.GL.getNewId(table); table[handle] = item; return handle; } }