import { assert , log , logIf , LogLevel } from './auxiliaries' ; import { byteSizeOfFormat } from './formatbytesizes' ; import { AllocationRegister } from './allocationregister' ; import { ContextMasquerade } from './contextmasquerade' ; import { WEBGL1_EXTENSIONS , WEBGL2_DEFAULT_EXTENSIONS , WEBGL2_EXTENSIONS } from './extensions' ; import { ExtensionsHash } from './extensionshash' ; import { GL2Facade } from './gl2facade' ; /**
 * A controller for either a WebGLRenderingContext or WebGL2RenderingContext. It requests a context, tracks context
 * attributes, extensions as well as multi frame specific rendering information and a (gpu)allocation registry.
 *
 * An instance of `Context` can be created only implicitly by requesting a context given a canvas element and its
 * dataset:
 * ```
 * const element: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById(canvasID);
 * this.context = Context.request(element); // element.dataset is used for attributes
 * ```
 * The context supports the following data-attributes:
 * ```
 * data-backend: 'auto' | 'webgl' | 'webgl2'
 * data-accumulation-format: 'auto' | 'float' | 'half' | 'byte'
 * ```
 *
 * At run-time, cached context features can be queried without a performance impact, e.g., frequent extension-based
 * branching:
 * ```
 * if(this.context.supportsVertexArrayObject) {
 *     this.context.vertexArrayObject.bindVertexArrayOES(...);
 *     ...
 * }
 * ```
 *
 * For convenience, protected extension names such as `EXT_frag_depth` are not prefixed by an underscore.
 */ export class Context { /**
     * Context creation attribute defaults. The defaults are taken directly from the spec.
     */ protected static readonly DEFAULT_ATTRIBUTES = { alpha : true , antialias : false , depth : true , failIfMajorPerformanceCaveat : false , premultipliedAlpha : true , preserveDrawingBuffer : false , stencil : false , } ; see backend protected _backend : Context . BackendType | undefined ; see gl protected _context : WebGLRenderingContext | WebGL2RenderingContext | undefined ; see mask protected _mask : ContextMasquerade | undefined ; see gl2facade protected _gl2 : GL2Facade ; param dataset returns protected static createMasqueradeFromGETorDataAttribute ( dataset ) { const mask = ContextMasquerade . fromGET ( ) ; if ( mask ) { return mask ; } if ( dataset . msqrdH ) { return ContextMasquerade . fromHash ( dataset . msqrdH as string ) ; } if ( dataset . msqrdP ) { return ContextMasquerade . fromPreset ( dataset . msqrdP as string ) ; } return undefined ; } param element param attributes see { Context . DEFAULT_ATTRIBUTES } returns static request ( element , attributes = Context . DEFAULT_ATTRIBUTES ) { const dataset = element . dataset ; const mask = Context . createMasqueradeFromGETorDataAttribute ( dataset ) ; /** Favor backend specification by masquerade over specification by data attribute. */ let request = mask ? ( mask . backend as string ) : dataset . backend ? ( dataset . backend as string ) . toLowerCase ( ) : 'auto' ; if ( ! ( request in Context . BackendRequestType ) ) { log ( LogLevel . Warning , `unknown backend '${ dataset . backend }' changed to '${ Context . BackendRequestType . auto }'` ) ; request = 'auto' ; } switch ( request ) { case Context . BackendRequestType . webgl : break ; case Context . BackendRequestType . experimental : case Context . BackendRequestType . webgl1 : case Context . BackendRequestType . experimental1 : request = Context . BackendRequestType . webgl ; break ; case Context . BackendRequestType . webgl2 : case Context . BackendRequestType . experimental2 : request = Context . BackendRequestType . webgl2 ; break ; default : request = Context . BackendRequestType . auto ; } let context ; if ( request !== Context . BackendRequestType . webgl ) { context = this . requestWebGL2 ( element , attributes ) ; } if ( ! context ) { context = this . requestWebGL1 ( element , attributes ) ; logIf ( context !== undefined && request === Context . BackendRequestType . webgl2 , LogLevel . Info , `backend changed to '${ Context . BackendRequestType . webgl }', given '${ request }'` ) ; } assert ( ! ! context , `creating a context failed` ) ; return new Context ( context , mask ) ; } param element param attributes see { Context . CONTEXT_ATTRIBUTES } returns { WebGLRenderingContext } protected static requestWebGL1 ( element , attributes = Context . DEFAULT_ATTRIBUTES ) { let context = element . getContext ( Context . BackendRequestType . webgl , attributes ) ; if ( context ) { return context ; } context = element . getContext ( Context . BackendRequestType . experimental , attributes ) as WebGLRenderingContext ; return context === null ? undefined : context ; } param element param attributes see { Context . CONTEXT_ATTRIBUTES } returns { WebGL2RenderingContext } protected static requestWebGL2 ( element , attributes = Context . DEFAULT_ATTRIBUTES ) { let context = element . getContext ( Context . BackendRequestType . webgl2 , attributes ) ; if ( context ) { return context ; } context = element . getContext ( Context . BackendRequestType . experimental2 , attributes ) as WebGL2RenderingContext ; return context === null ? undefined : context ; } /**
     * Cached attributes of the context.
     */ protected _attributes : WebGLContextAttributes | undefined = undefined ; protected queryAttributes ( ) { const attributes = this . _context ! . getContextAttributes ( ) ; if ( attributes === null ) { log ( LogLevel . Error , `querying context attributes failed (probably blocked)` ) ; return ; } this . _attributes = attributes ; } link get alpha ( ) : boolean { return this . _attributes ? this . _attributes ! . alpha as boolean : false ; } link get antialias ( ) : boolean { return this . _attributes ? this . _attributes ! . antialias as boolean : false ; } link get depth ( ) : boolean { return this . _attributes ? this . _attributes ! . depth as boolean : false ; } link get failIfMajorPerformanceCaveat ( ) : boolean { return this . _attributes ? this . _attributes ! . failIfMajorPerformanceCaveat as boolean : false ; } link get premultipliedAlpha ( ) : boolean { return this . _attributes ? this . _attributes ! . premultipliedAlpha as boolean : false ; } link get preserveDrawingBuffer ( ) : boolean { return this . _attributes ? this . _attributes ! . preserveDrawingBuffer as boolean : false ; } link get stencil ( ) : boolean { return this . _attributes ? this . _attributes ! . stencil as boolean : false ; } /**
     * Cached extension supported by the context.
     */ protected _extensions : Array < string > = new Array < string > ( ) ; param extension returns supports ( extension ) { if ( this . _mask && this . _mask . extensionsConceal . indexOf ( extension ) > - 1 ) { return false ; } switch ( this . _backend ) { case Context . BackendType . WebGL1 : assert ( WEBGL1_EXTENSIONS . indexOf ( extension ) > - 1 , `extension ${ extension } not available to WebGL1` ) ; break ; case Context . BackendType . WebGL2 : assert ( WEBGL2_DEFAULT_EXTENSIONS . indexOf ( extension ) === - 1 , `extension ${ extension } supported by default in WebGL2` ) ; assert ( WEBGL2_EXTENSIONS . indexOf ( extension ) > - 1 , `extension ${ extension } not available to WebGL2` ) ; break ; default : break ; } return this . _extensions . indexOf ( extension ) > - 1 ; } param extensions enable ( extensions ) { for ( const extension of extensions ) { if ( this . isWebGL1 && WEBGL1_EXTENSIONS . indexOf ( extension ) === - 1 ) { continue ; } if ( this . isWebGL2 && WEBGL2_EXTENSIONS . indexOf ( extension ) === - 1 ) { continue ; } if ( this . supports ( extension ) === false ) { continue ; } this . extension ( undefined , extension ) ; } } /**
     * Queries all extensions for the current context and stores the result (supported or not supported). This is
     * relevant to avoid continuous searches or regexp matching or substring queries in the complete extension string.
     * Instead, the support is queried once and can be explicitly request in the public interface using properties.
     *
     * This function should get called only once per Context instance.
     */ protected queryExtensionSupport ( ) { const extensions = this . _context ! . getSupportedExtensions ( ) ; if ( extensions === null ) { log ( LogLevel . Error , `querying supported extensions failed (probably blocked)` ) ; return ; } for ( const extension of extensions ) { if ( this . _mask && this . _mask . extensionsConceal . indexOf ( extension ) > - 1 ) { continue ; } this . _extensions . push ( extension ) ; } if ( this . _backend === Context . BackendType . WebGL1 ) { this . ANGLE_instanced_arrays_supported = this . supports ( 'ANGLE_instanced_arrays' ) ; this . EXT_blend_minmax_supported = this . supports ( 'EXT_blend_minmax' ) ; this . EXT_color_buffer_half_float_supported = this . supports ( 'EXT_color_buffer_half_float' ) ; this . EXT_disjoint_timer_query_supported = this . supports ( 'EXT_disjoint_timer_query' ) ; this . EXT_frag_depth_supported = this . supports ( 'EXT_frag_depth' ) ; this . EXT_sRGB_supported = this . supports ( 'EXT_sRGB' ) ; this . EXT_shader_texture_lod_supported = this . supports ( 'EXT_shader_texture_lod' ) ; this . OES_element_index_uint_supported = this . supports ( 'OES_element_index_uint' ) ; this . OES_standard_derivatives_supported = this . supports ( 'OES_standard_derivatives' ) ; this . OES_texture_float_supported = this . supports ( 'OES_texture_float' ) ; this . OES_texture_half_float_supported = this . supports ( 'OES_texture_half_float' ) ; this . OES_vertex_array_object_supported = this . supports ( 'OES_vertex_array_object' ) ; this . WEBGL_color_buffer_float_supported = this . supports ( 'WEBGL_color_buffer_float' ) ; this . WEBGL_depth_texture_supported = this . supports ( 'WEBGL_depth_texture' ) ; this . WEBGL_draw_buffers_supported = this . supports ( 'WEBGL_draw_buffers' ) ; } if ( this . _backend === Context . BackendType . WebGL2 ) { this . EXT_color_buffer_float_supported = this . supports ( 'EXT_color_buffer_float' ) ; this . EXT_disjoint_timer_query_webgl2_supported = this . supports ( 'EXT_disjoint_timer_query_webgl2' ) ; } this . EXT_texture_filter_anisotropic_supported = this . supports ( 'EXT_texture_filter_anisotropic' ) ; this . OES_texture_float_linear_supported = this . supports ( 'OES_texture_float_linear' ) ; this . OES_texture_half_float_linear_supported = this . supports ( 'OES_texture_half_float_linear' ) ; this . WEBGL_compressed_texture_astc_supported = this . supports ( 'WEBGL_compressed_texture_astc' ) ; this . WEBGL_compressed_texture_atc_supported = this . supports ( 'WEBGL_compressed_texture_atc' ) ; this . WEBGL_compressed_texture_etc_supported = this . supports ( 'WEBGL_compressed_texture_etc' ) ; this . WEBGL_compressed_texture_etc1_supported = this . supports ( 'WEBGL_compressed_texture_etc1' ) ; this . WEBGL_compressed_texture_pvrtc_supported = this . supports ( 'WEBGL_compressed_texture_pvrtc' ) ; this . WEBGL_compressed_texture_s3tc_supported = this . supports ( 'WEBGL_compressed_texture_s3tc' ) ; this . WEBGL_compressed_texture_s3tc_srgb_supported = this . supports ( 'WEBGL_compressed_texture_s3tc_srgb' ) ; this . WEBGL_debug_renderer_info_supported = this . supports ( 'WEBGL_debug_renderer_info' ) ; this . WEBGL_debug_shaders_supported = this . supports ( 'WEBGL_debug_shaders' ) ; this . WEBGL_lose_context_supported = this . supports ( 'WEBGL_lose_context' ) ; } param out param extension returns protected extension ( out , extension ) { if ( out === undefined ) { assert ( this . supports ( extension ) , `extension ${ extension } expected to be supported` ) ; out = this . _context ! . getExtension ( extension ) ; } return out ; } /**
     * Context this is of type 'any' for now, since WebGL2RenderingContext not available but supported. This
     * constructor is protected to enforce context creation using `request`. It queries extension support and
     * configures context specifics for convenience, e.g., HALF_FLOAT format.
     */ protected constructor ( context , mask ) { this . _context = context ; this . _mask = mask ; const contextString = context . toString ( ) ; { const webgl1 = /WebGLRenderingContext/ . test ( contextString ) || /CaptureContext/ . test ( contextString ) ; const webgl2 = /WebGL2RenderingContext/ . test ( contextString ) ; this . _backend = webgl1 ? Context . BackendType . WebGL1 : webgl2 ? Context . BackendType . WebGL2 : undefined ; } assert ( this . _backend !== undefined && this . _backend . valueOf ( ) !== Context . BackendType . Invalid . valueOf ( ) , `context is neither webgl nor webgl2, given ${ contextString }` ) ; this . queryAttributes ( ) ; this . queryExtensionSupport ( ) ; if ( this . _mask && this . _mask . functionsUndefine ) { for ( const func in this . _mask . functionsUndefine ) { ( this . _context as any ) [ func ] = undefined ; } } this . _gl2 = new GL2Facade ( this ) ; } see allocationRegister protected _allocationRegister = new AllocationRegister ( ) ; /**
     * The context's GPU allocation register for use of tracking memory allocations.
     */ get allocationRegister ( ) : AllocationRegister { return this . _allocationRegister ; } returns get backend ( ) : Context . BackendType | undefined { return this . _backend ; } /**
     * Provides a human-readable string of the backend.
     */ get backendString ( ) : string | undefined { switch ( this . _backend ) { case Context . BackendType . WebGL1 : return 'WebGL' ; case Context . BackendType . WebGL2 : return 'WebGL2' ; default : return undefined ; } } /**
     * Provides an array of all extensions supported by the used WebGL1/2 context.
     */ get extensions ( ) : Array < string > { return this . _extensions ; } /**
     * Masquerade object applied to a context instance.
     */ get mask ( ) : ContextMasquerade | undefined { return this . _mask ; } /**
     * Access to either the WebGLRenderingContext or WebGL2RenderingContext.
     */ get gl ( ) : any { return this . _context ; } /**
     * WebGL2 facade for WebGL2 API like access to features mandatory to this engine.
     */ get gl2facade ( ) : GL2Facade { return this . _gl2 ; } /**
     * True if the context is a WebGL1 context, otherwise false.
     */ get isWebGL1 ( ) : boolean { return this . _backend === Context . BackendType . WebGL1 ; } /**
     * True if the context is a WebGL2 context, otherwise false.
     */ get isWebGL2 ( ) : boolean { return this . _backend === Context . BackendType . WebGL2 ; } protected ANGLE_instanced_arrays : any ; protected ANGLE_instanced_arrays_supported : boolean ; get supportsInstancedArrays ( ) : boolean { return this . ANGLE_instanced_arrays_supported ; } get instancedArrays ( ) : any { return this . extension ( this . ANGLE_instanced_arrays , 'ANGLE_instanced_arrays' ) ; } protected EXT_blend_minmax : any ; protected EXT_blend_minmax_supported : boolean ; get supportsBlendMinmax ( ) : boolean { return this . EXT_blend_minmax_supported ; } get blendMinmax ( ) : any { return this . extension ( this . EXT_blend_minmax , 'EXT_blend_minmax' ) ; } protected EXT_color_buffer_half_float : any ; protected EXT_color_buffer_half_float_supported : boolean ; get supportsColorBufferHalfFloat ( ) : boolean { return this . EXT_color_buffer_half_float_supported ; } get colorBufferHalfFloat ( ) : any { return this . extension ( this . EXT_color_buffer_half_float , 'EXT_color_buffer_half_float' ) ; } protected EXT_disjoint_timer_query : any ; protected EXT_disjoint_timer_query_supported : boolean ; get supportsDisjointTimerQuery ( ) : boolean { return this . EXT_disjoint_timer_query_supported ; } get disjointTimerQuery ( ) : any { return this . extension ( this . EXT_disjoint_timer_query , 'EXT_disjoint_timer_query' ) ; } protected EXT_disjoint_timer_query_webgl2 : any ; protected EXT_disjoint_timer_query_webgl2_supported : boolean ; get supportsDisjointTimerQueryWebGL2 ( ) : boolean { return this . EXT_disjoint_timer_query_webgl2_supported ; } get disjointTimerQueryWebGL2 ( ) : any { return this . extension ( this . EXT_disjoint_timer_query_webgl2 , 'EXT_disjoint_timer_query_webgl2' ) ; } protected EXT_frag_depth : any ; protected EXT_frag_depth_supported : boolean ; get supportsFragDepth ( ) : boolean { return this . EXT_frag_depth_supported ; } get fragDepth ( ) : any { return this . extension ( this . EXT_frag_depth , 'EXT_frag_depth' ) ; } protected EXT_sRGB : any ; protected EXT_sRGB_supported : boolean ; get supportsSRGB ( ) : boolean { return this . EXT_sRGB_supported ; } get sRGB ( ) : any { return this . extension ( this . EXT_sRGB , 'EXT_sRGB' ) ; } protected EXT_shader_texture_lod : any ; protected EXT_shader_texture_lod_supported : boolean ; get supportsShaderTextureLOD ( ) : boolean { return this . EXT_shader_texture_lod_supported ; } get shaderTextureLOD ( ) : any { return this . extension ( this . EXT_shader_texture_lod , 'EXT_shader_texture_lod' ) ; } protected EXT_texture_filter_anisotropic : any ; protected EXT_texture_filter_anisotropic_supported : boolean ; get supportsTextureFilterAnisotropic ( ) : boolean { return this . EXT_texture_filter_anisotropic_supported ; } get textureFilterAnisotropic ( ) : any { return this . extension ( this . EXT_texture_filter_anisotropic , 'EXT_texture_filter_anisotropic' ) ; } protected OES_element_index_uint : any ; protected OES_element_index_uint_supported : boolean ; get supportsElementIndexUint ( ) : boolean { return this . OES_element_index_uint_supported ; } get elementIndexUint ( ) : any { return this . extension ( this . OES_element_index_uint , 'OES_element_index_uint' ) ; } protected OES_standard_derivatives : any ; protected OES_standard_derivatives_supported : boolean ; get supportsStandardDerivatives ( ) : boolean { return this . OES_standard_derivatives_supported ; } get standardDerivatives ( ) : any { return this . extension ( this . OES_standard_derivatives , 'OES_standard_derivatives' ) ; } protected OES_texture_float : any ; protected OES_texture_float_supported : boolean ; get supportsTextureFloat ( ) : boolean { return this . OES_texture_float_supported ; } get textureFloat ( ) : any { return this . extension ( this . OES_texture_float , 'OES_texture_float' ) ; } protected OES_texture_float_linear : any ; protected OES_texture_float_linear_supported : boolean ; get supportsTextureFloatLinear ( ) : boolean { return this . OES_texture_float_linear_supported ; } get textureFloatLinear ( ) : any { return this . extension ( this . OES_texture_float_linear , 'OES_texture_float_linear' ) ; } protected OES_texture_half_float : any ; protected OES_texture_half_float_supported : boolean ; get supportsTextureHalfFloat ( ) : boolean { return this . OES_texture_half_float_supported ; } get textureHalfFloat ( ) : any { return this . extension ( this . OES_texture_half_float , 'OES_texture_half_float' ) ; } protected OES_texture_half_float_linear : any ; protected OES_texture_half_float_linear_supported : boolean ; get supportsTextureHalfFloatLinear ( ) : boolean { return this . OES_texture_half_float_linear_supported ; } get textureHalfFloatLinear ( ) : any { return this . extension ( this . OES_texture_half_float_linear , 'OES_texture_half_float_linear' ) ; } protected OES_vertex_array_object : any ; protected OES_vertex_array_object_supported : boolean ; get supportsVertexArrayObject ( ) : boolean { return this . OES_vertex_array_object_supported ; } get vertexArrayObject ( ) : any { return this . extension ( this . OES_vertex_array_object , 'OES_vertex_array_object' ) ; } protected WEBGL_color_buffer_float : any ; protected WEBGL_color_buffer_float_supported : boolean ; protected EXT_color_buffer_float : any ; protected EXT_color_buffer_float_supported : boolean ; get supportsColorBufferFloat ( ) : boolean | undefined { switch ( this . _backend ) { case Context . BackendType . WebGL1 : return this . WEBGL_color_buffer_float_supported ; case Context . BackendType . WebGL2 : return this . EXT_color_buffer_float_supported ; default : return undefined ; } } get colorBufferFloat ( ) : any | undefined { switch ( this . _backend ) { case Context . BackendType . WebGL1 : return this . extension ( this . WEBGL_color_buffer_float , 'WEBGL_color_buffer_float' ) ; case Context . BackendType . WebGL2 : return this . extension ( this . EXT_color_buffer_float , 'EXT_color_buffer_float' ) ; default : return undefined ; } } protected WEBGL_compressed_texture_astc : any ; protected WEBGL_compressed_texture_astc_supported : boolean ; get supportsCompressedTextureASTC ( ) : boolean { return this . WEBGL_compressed_texture_astc_supported ; } get compressedTextureASTC ( ) : any { return this . extension ( this . WEBGL_compressed_texture_astc , 'WEBGL_compressed_texture_astc' ) ; } protected WEBGL_compressed_texture_atc : any ; protected WEBGL_compressed_texture_atc_supported : boolean ; get supportsCompressedTextureATC ( ) : boolean { return this . WEBGL_compressed_texture_atc_supported ; } get compressedTextureATC ( ) : any { return this . extension ( this . WEBGL_compressed_texture_atc , 'WEBGL_compressed_texture_atc' ) ; } protected WEBGL_compressed_texture_etc : any ; protected WEBGL_compressed_texture_etc_supported : boolean ; get supportsCompressedTextureETC ( ) : boolean { return this . WEBGL_compressed_texture_etc_supported ; } get compressedTextureETC ( ) : any { return this . extension ( this . WEBGL_compressed_texture_etc , 'WEBGL_compressed_texture_etc' ) ; } protected WEBGL_compressed_texture_etc1 : any ; protected WEBGL_compressed_texture_etc1_supported : boolean ; get supportsCompressedTextureETC1 ( ) : boolean { return this . WEBGL_compressed_texture_etc1_supported ; } get compressedTextureETC1 ( ) : any { return this . extension ( this . WEBGL_compressed_texture_etc1 , 'WEBGL_compressed_texture_etc1' ) ; } protected WEBGL_compressed_texture_pvrtc : any ; protected WEBGL_compressed_texture_pvrtc_supported : boolean ; get supportsCompressedTexturePVRTC ( ) : boolean { return this . WEBGL_compressed_texture_pvrtc_supported ; } get compressedTexturePVRTC ( ) : any { return this . extension ( this . WEBGL_compressed_texture_pvrtc , 'WEBGL_compressed_texture_pvrtc' ) ; } protected WEBGL_compressed_texture_s3tc : any ; protected WEBGL_compressed_texture_s3tc_supported : boolean ; get supportsCompressedTextureS3TC ( ) : boolean { return this . WEBGL_compressed_texture_s3tc_supported ; } get compressedTextureS3TC ( ) : any { return this . extension ( this . WEBGL_compressed_texture_s3tc , 'WEBGL_compressed_texture_s3tc' ) ; } protected WEBGL_compressed_texture_s3tc_srgb : any ; protected WEBGL_compressed_texture_s3tc_srgb_supported : boolean ; get supportsCompressedTextureS3TCSRGB ( ) : boolean { return this . WEBGL_compressed_texture_s3tc_srgb_supported ; } get compressedTextureS3TCSRGB ( ) : any { return this . extension ( this . WEBGL_compressed_texture_s3tc_srgb , 'WEBGL_compressed_texture_s3tc_srgb' ) ; } protected WEBGL_debug_renderer_info : any ; protected WEBGL_debug_renderer_info_supported : boolean ; get supportsDebugRendererInfo ( ) : boolean { return this . WEBGL_debug_renderer_info_supported ; } get debugRendererInfo ( ) : any { return this . extension ( this . WEBGL_debug_renderer_info , 'WEBGL_debug_renderer_info' ) ; } protected WEBGL_debug_shaders : any ; protected WEBGL_debug_shaders_supported : boolean ; get supportsDebugShaders ( ) : boolean { return this . WEBGL_debug_shaders_supported ; } get debugShaders ( ) : any { return this . extension ( this . WEBGL_debug_shaders , 'WEBGL_debug_shaders' ) ; } protected WEBGL_depth_texture : any ; protected WEBGL_depth_texture_supported : boolean ; get supportsDepthTexture ( ) : boolean { return this . WEBGL_depth_texture_supported ; } get depthTexture ( ) : any { return this . extension ( this . WEBGL_depth_texture , 'WEBGL_depth_texture' ) ; } protected WEBGL_draw_buffers : any ; protected WEBGL_draw_buffers_supported : boolean ; get supportsDrawBuffers ( ) : boolean { return this . WEBGL_draw_buffers_supported ; } get drawBuffers ( ) : any { return this . extension ( this . WEBGL_draw_buffers , 'WEBGL_draw_buffers' ) ; } protected WEBGL_lose_context : any ; protected WEBGL_lose_context_supported : boolean ; get supportsLoseContext ( ) : boolean { return this . WEBGL_lose_context_supported ; } get loseContext ( ) : any { return this . extension ( this . WEBGL_lose_context , 'WEBGL_lose_context' ) ; } /**
     * True if WebGL2 blitFramebuffer is supported, false otherwise. This is experimental technology.
     */ get supportsBlitFramebuffer ( ) : boolean { return ( this . _context as any ) . blitFramebuffer !== undefined ; } /**
     * True if WebGL2 readBuffer is supported, false otherwise. This is experimental technology.
     */ get supportsReadBuffer ( ) : boolean { return ( this . _context as any ) . readBuffer !== undefined ; } /**
     * True if WebGL2 texImage3D draft is supported, false otherwise. This is experimental technology.
     */ get supportsTexImage3D ( ) : boolean { return ( this . _context as any ) . texImage3D !== undefined ; } param ( pname ) { assert ( ! ! this . _context , `expected context to be valid` ) ; return this . _context ! . getParameter ( pname ) ; } /**
     * Provides the context's extension hash. The hash can be used for context masquerade.
     */ hash ( ) { return ExtensionsHash . encode ( this . _backend as Context . BackendType , this . _extensions ) ; } returns about ( ) { const available = 'ok' ; const unavailable = 'na' ; if ( this . _backend === Context . BackendType . Invalid ) { return new Array < [ string , number | string ] > ( ) ; } assert ( ! ! this . _context , `expected context to be valid` ) ; const context = this . _context ! ; const pNamesAndValues = new Array < [ string , number | string ] > ( ) ; pNamesAndValues . push ( [ 'BACKEND (GLOPERATE)' , this . backend as Context . BackendType ] ) ; pNamesAndValues . push ( [ 'CONTEXT_HASH (GLOPERATE)' , this . hash ( ) ] ) ; pNamesAndValues . push ( [ 'RENDERER' , this . param ( context . RENDERER ) ] ) ; pNamesAndValues . push ( [ 'VENDOR' , this . param ( context . VENDOR ) ] ) ; pNamesAndValues . push ( [ 'VERSION' , this . param ( context . VERSION ) ] ) ; pNamesAndValues . push ( [ 'SHADING_LANGUAGE_VERSION' , this . param ( context . SHADING_LANGUAGE_VERSION ) ] ) ; pNamesAndValues . push ( [ 'UNMASKED_VENDOR_WEBGL' , ! this . supportsDebugRendererInfo ? unavailable : this . param ( this . debugRendererInfo . UNMASKED_VENDOR_WEBGL ) ] ) ; pNamesAndValues . push ( [ 'UNMASKED_RENDERER_WEBGL' , ! this . supportsDebugRendererInfo ? unavailable : this . param ( this . debugRendererInfo . UNMASKED_RENDERER_WEBGL ) ] ) ; pNamesAndValues . push ( [ 'ALPHA (ATTRIBUTE)' , String ( this . alpha ) ] ) ; pNamesAndValues . push ( [ 'ANTIALIAS (ATTRIBUTE)' , String ( this . antialias ) ] ) ; pNamesAndValues . push ( [ 'DEPTH (ATTRIBUTE)' , String ( this . depth ) ] ) ; pNamesAndValues . push ( [ 'FAIL_IF_MAJOR_PERFORMANCE_CAVEAT (ATTRIBUTE)' , String ( this . failIfMajorPerformanceCaveat ) ] ) ; pNamesAndValues . push ( [ 'PREMULTIPLIED_ALPHA (ATTRIBUTE)' , String ( this . premultipliedAlpha ) ] ) ; pNamesAndValues . push ( [ 'PRESERVE_DRAWING_BUFFER (ATTRIBUTE)' , String ( this . preserveDrawingBuffer ) ] ) ; pNamesAndValues . push ( [ 'STENCIL (ATTRIBUTE)' , String ( this . stencil ) ] ) ; pNamesAndValues . push ( [ 'DEVICE_PIXEL_RATIO (WINDOW)' , window . devicePixelRatio ] ) ; pNamesAndValues . push ( [ 'APP_CODE_NAME (NAVIGATOR)' , window . navigator . appCodeName ] ) ; pNamesAndValues . push ( [ 'APP_NAME (NAVIGATOR)' , window . navigator . appName ] ) ; pNamesAndValues . push ( [ 'APP_VERSION (NAVIGATOR)' , window . navigator . appVersion ] ) ; pNamesAndValues . push ( [ 'PLATFORM (NAVIGATOR)' , window . navigator . platform ] ) ; pNamesAndValues . push ( [ 'HARDWARE_CONCURRENCY (NAVIGATOR)' , window . navigator . appCodeName ] ) ; pNamesAndValues . push ( [ 'VENDOR (NAVIGATOR)' , window . navigator . vendor ] ) ; pNamesAndValues . push ( [ 'VENDOR_SUB (NAVIGATOR)' , window . navigator . vendorSub ] ) ; pNamesAndValues . push ( [ 'MAX_COMBINED_TEXTURE_IMAGE_UNITS' , this . param ( context . MAX_COMBINED_TEXTURE_IMAGE_UNITS ) ] ) ; pNamesAndValues . push ( [ 'MAX_CUBE_MAP_TEXTURE_SIZE' , this . param ( context . MAX_CUBE_MAP_TEXTURE_SIZE ) ] ) ; pNamesAndValues . push ( [ 'MAX_FRAGMENT_UNIFORM_VECTORS' , this . param ( context . MAX_FRAGMENT_UNIFORM_VECTORS ) ] ) ; pNamesAndValues . push ( [ 'MAX_RENDERBUFFER_SIZE' , this . param ( context . MAX_RENDERBUFFER_SIZE ) ] ) ; pNamesAndValues . push ( [ 'MAX_TEXTURE_IMAGE_UNITS' , this . param ( context . MAX_TEXTURE_IMAGE_UNITS ) ] ) ; pNamesAndValues . push ( [ 'MAX_TEXTURE_SIZE' , this . param ( context . MAX_TEXTURE_SIZE ) ] ) ; pNamesAndValues . push ( [ 'MAX_VARYING_VECTORS' , this . param ( context . MAX_VARYING_VECTORS ) ] ) ; pNamesAndValues . push ( [ 'MAX_VERTEX_ATTRIBS' , this . param ( context . MAX_VERTEX_ATTRIBS ) ] ) ; pNamesAndValues . push ( [ 'MAX_VERTEX_TEXTURE_IMAGE_UNITS' , this . param ( context . MAX_VERTEX_TEXTURE_IMAGE_UNITS ) ] ) ; pNamesAndValues . push ( [ 'MAX_VERTEX_UNIFORM_VECTORS' , this . param ( context . MAX_VERTEX_UNIFORM_VECTORS ) ] ) ; const MAX_VIEWPORT_DIMS = this . param ( context . MAX_VIEWPORT_DIMS ) ; pNamesAndValues . push ( [ 'MAX_VIEWPORT_DIMS (WIDTH)' , MAX_VIEWPORT_DIMS ? MAX_VIEWPORT_DIMS [ 0 ] : null ] ) ; pNamesAndValues . push ( [ 'MAX_VIEWPORT_DIMS (HEIGHT)' , MAX_VIEWPORT_DIMS ? MAX_VIEWPORT_DIMS [ 1 ] : null ] ) ; if ( this . isWebGL2 ) { const context = this . _context as WebGL2RenderingContext ; pNamesAndValues . push ( [ 'MAX_3D_TEXTURE_SIZE' , this . param ( context . MAX_3D_TEXTURE_SIZE ) ] ) ; pNamesAndValues . push ( [ 'MAX_ARRAY_TEXTURE_LAYERS' , this . param ( context . MAX_ARRAY_TEXTURE_LAYERS ) ] ) ; pNamesAndValues . push ( [ 'MAX_CLIENT_WAIT_TIMEOUT_WEBGL' , this . param ( context . MAX_CLIENT_WAIT_TIMEOUT_WEBGL ) ] ) ; pNamesAndValues . push ( [ 'MAX_COLOR_ATTACHMENTS' , this . param ( context . MAX_COLOR_ATTACHMENTS ) ] ) ; pNamesAndValues . push ( [ 'MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS' , this . param ( context . MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS ) ] ) ; pNamesAndValues . push ( [ 'MAX_COMBINED_UNIFORM_BLOCKS' , this . param ( context . MAX_COMBINED_UNIFORM_BLOCKS ) ] ) ; pNamesAndValues . push ( [ 'MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS' , this . param ( context . MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS ) ] ) ; pNamesAndValues . push ( [ 'MAX_DRAW_BUFFERS' , this . param ( context . MAX_DRAW_BUFFERS ) ] ) ; pNamesAndValues . push ( [ 'MAX_ELEMENT_INDEX' , this . param ( context . MAX_ELEMENT_INDEX ) ] ) ; pNamesAndValues . push ( [ 'MAX_ELEMENTS_INDICES' , this . param ( context . MAX_ELEMENTS_INDICES ) ] ) ; pNamesAndValues . push ( [ 'MAX_ELEMENTS_VERTICES' , this . param ( context . MAX_ELEMENTS_VERTICES ) ] ) ; pNamesAndValues . push ( [ 'MAX_FRAGMENT_INPUT_COMPONENTS' , this . param ( context . MAX_FRAGMENT_INPUT_COMPONENTS ) ] ) ; pNamesAndValues . push ( [ 'MAX_FRAGMENT_UNIFORM_BLOCKS' , this . param ( context . MAX_FRAGMENT_UNIFORM_BLOCKS ) ] ) ; pNamesAndValues . push ( [ 'MAX_FRAGMENT_UNIFORM_COMPONENTS' , this . param ( context . MAX_FRAGMENT_UNIFORM_COMPONENTS ) ] ) ; pNamesAndValues . push ( [ 'MAX_PROGRAM_TEXEL_OFFSET' , this . param ( context . MAX_PROGRAM_TEXEL_OFFSET ) ] ) ; pNamesAndValues . push ( [ 'MAX_SAMPLES' , this . param ( context . MAX_SAMPLES ) ] ) ; pNamesAndValues . push ( [ 'MAX_SERVER_WAIT_TIMEOUT' , this . param ( context . MAX_SERVER_WAIT_TIMEOUT ) ] ) ; pNamesAndValues . push ( [ 'MAX_TEXTURE_LOD_BIAS' , this . param ( context . MAX_TEXTURE_LOD_BIAS ) ] ) ; pNamesAndValues . push ( [ 'MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS' , this . param ( context . MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS ) ] ) ; pNamesAndValues . push ( [ 'MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS' , this . param ( context . MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS ) ] ) ; pNamesAndValues . push ( [ 'MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS' , this . param ( context . MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS ) ] ) ; pNamesAndValues . push ( [ 'MAX_UNIFORM_BLOCK_SIZE' , this . param ( context . MAX_UNIFORM_BLOCK_SIZE ) ] ) ; pNamesAndValues . push ( [ 'MAX_UNIFORM_BUFFER_BINDINGS' , this . param ( context . MAX_UNIFORM_BUFFER_BINDINGS ) ] ) ; pNamesAndValues . push ( [ 'MAX_VARYING_COMPONENTS' , this . param ( context . MAX_VARYING_COMPONENTS ) ] ) ; pNamesAndValues . push ( [ 'MAX_VERTEX_OUTPUT_COMPONENTS' , this . param ( context . MAX_VERTEX_OUTPUT_COMPONENTS ) ] ) ; pNamesAndValues . push ( [ 'MAX_VERTEX_UNIFORM_BLOCKS' , this . param ( context . MAX_VERTEX_UNIFORM_BLOCKS ) ] ) ; pNamesAndValues . push ( [ 'MAX_VERTEX_UNIFORM_COMPONENTS' , this . param ( context . MAX_VERTEX_UNIFORM_COMPONENTS ) ] ) ; pNamesAndValues . push ( [ 'MIN_PROGRAM_TEXEL_OFFSET' , this . param ( context . MIN_PROGRAM_TEXEL_OFFSET ) ] ) ; } if ( this . isWebGL1 ) { for ( const extension of WEBGL1_EXTENSIONS ) { pNamesAndValues . push ( [ extension , this . supports ( extension ) ? available : unavailable ] ) ; } } else if ( this . isWebGL2 ) { for ( const extension of WEBGL2_DEFAULT_EXTENSIONS ) { pNamesAndValues . push ( [ `${ extension } (default)` , available ] ) ; } for ( const extension of WEBGL2_EXTENSIONS ) { pNamesAndValues . push ( [ extension , this . supports ( extension ) ? available : unavailable ] ) ; } } return pNamesAndValues ; } /**
     * Creates a well formated about string, e.g., for logging.
     */ aboutString ( ) { const about = this . about ( ) ; let maxPNameLength = 0 ; for ( const tuple of about ) { maxPNameLength = Math . max ( tuple [ 0 ] . length , maxPNameLength ) ; } let index = 0 ; let message = `` ; const extensionSeparator = this . isWebGL2 ? 63 + WEBGL2_DEFAULT_EXTENSIONS . length : - 1 ; for ( const tuple of about ) { switch ( index ) { case 2 : case 6 : case 8 : case 15 : case 16 : case 23 : case 35 : case 63 : case extensionSeparator : message += `\n` ; break ; default : break ; } message += `  ${ tuple [ 0 ] } ${ '-' . repeat ( maxPNameLength - tuple [ 0 ] . length ) }-- ${ tuple [ 1 ] }\n` ; ++ index ; } message += `\n` ; return message ; } param verbosity logAbout ( verbosity = LogLevel . Info ) { log ( verbosity , `context.about\n\n` + this . aboutString ( ) ) ; } /**
     * Invokes `logAbout` @see logAbout ) iff the given statement has resolved to true.
     *  param statement param verbosity logAboutIf ( statement , verbosity = LogLevel . Info ) { logIf ( statement , verbosity , `context.about\n\n` + this . aboutString ( ) ) ; } /**
     * Provides the size in bytes of certain WebGL format enumerator. Please note that some byte sizes might vary based
     * on context attributes or the bound render, thus, DEPTH_COMPONENT and DEPTH_STENCIL are not covered by this
     * function. @see  byteSizeOfFormat byteSizeOfFormat ( format ) { return byteSizeOfFormat ( this , format ) ; } } export namespace Context { /**
     * Supported OpenGL backend types.
     */ export enum BackendType { Invalid = 'invalid' , WebGL1 = 'webgl1' , WebGL2 = 'webgl2' } /**
     * The list of valid backend identifiers that can be requested and matched to backend types.
     * List adopted from https://developer.mozilla.org/de/docs/Web/API/HTMLCanvasElement/getContext.
     */ export enum BackendRequestType { auto = 'auto' , webgl = 'webgl' , experimental = 'experimental-webgl' , webgl1 = 'webgl1' , experimental1 = 'experimental-webgl1' , webgl2 = 'webgl2' , experimental2 = 'experimental-webgl2' } }