import { assert , logIf , LogLevel } from './auxiliaries' ; import { Context } from './context' ; export type TexImage2DData = GLintptr | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | ImageData | ArrayBufferView | undefined ; export type TexImage3DData = GLintptr | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap | ImageData | ArrayBufferView | undefined ; /**
 * A WebGL 2 facade, simplifying the access to gl functions that are either not available, exposed via extension or
 * supported directly, e.g., in webgl2. All gl features/interfaces handled by this facade are mandatory.
 */ export class GL2Facade { param context constructor ( context ) { assert ( context !== undefined , `gl2 facade expects a valid WebGL context` ) ; this . queryHalfFloatSupport ( context ) ; this . queryColorAttachments ( context ) ; this . queryInstancedArraySupport ( context ) ; this . queryDrawBuffersSupport ( context ) ; this . queryVertexArrayObjectSupport ( context ) ; this . queryMaxUniformVec3Components ( context ) ; this . queryBufferSubDataInterface ( context ) ; this . queryTexImageInterface ( context ) ; } /**
     * Stores the HALF_FLOAT enum if supported. @see  HALF_FLOAT protected _halfFloat : GLenum ; /**
     * The HALF_FLOAT format enum. Is `undefined` if not supported.
     */ get HALF_FLOAT ( ) : GLenum { return this . _halfFloat ; } /**
     *  For WebGL1 the HALF_FLOAT enum needs to be saved via the extension object.
     */ protected queryHalfFloatSupport ( context ) { switch ( context . backend ) { case Context . BackendType . WebGL1 : this . _halfFloat = context . supportsTextureHalfFloat && context . textureHalfFloat ? context . textureHalfFloat . HALF_FLOAT_OES : undefined ; break ; case Context . BackendType . WebGL2 : default : this . _halfFloat = context . gl . HALF_FLOAT ; break ; } } /**
     * Stores the lowest color attachment identifier.
     */ protected _colorAttachmentMin : GLenum ; /**
     * The lowest color attachment identifier format enum.
     */ get COLOR_ATTACHMENT_MIN ( ) : GLenum { return this . _colorAttachmentMin ; } /**
     * Stores the highest supported color attachment identifier.
     */ protected _colorAttachmentMax : GLenum ; /**
     * Stores all context/backend sepcific color attachment identifier for COLOR_ATTACHMENT# getter.
     */ protected _colorAttachments : Array < GLenum > ; /**
     * The lowest color attachment identifier format enum.
     * Is at least `COLOR_ATTACHMENT_MIN`.
     */ get COLOR_ATTACHMENT_MAX ( ) : GLenum { return this . _colorAttachmentMax ; } get COLOR_ATTACHMENT0 ( ) : GLenum { return this . _colorAttachments [ 0 ] ; } get COLOR_ATTACHMENT1 ( ) : GLenum { return this . _colorAttachments [ 1 ] ; } get COLOR_ATTACHMENT2 ( ) : GLenum { return this . _colorAttachments [ 2 ] ; } get COLOR_ATTACHMENT3 ( ) : GLenum { return this . _colorAttachments [ 3 ] ; } get COLOR_ATTACHMENT4 ( ) : GLenum { return this . _colorAttachments [ 4 ] ; } get COLOR_ATTACHMENT5 ( ) : GLenum { return this . _colorAttachments [ 5 ] ; } get COLOR_ATTACHMENT6 ( ) : GLenum { return this . _colorAttachments [ 6 ] ; } get COLOR_ATTACHMENT7 ( ) : GLenum { return this . _colorAttachments [ 7 ] ; } get COLOR_ATTACHMENT8 ( ) : GLenum { return this . _colorAttachments [ 8 ] ; } get COLOR_ATTACHMENT9 ( ) : GLenum { return this . _colorAttachments [ 9 ] ; } get COLOR_ATTACHMENT10 ( ) : GLenum { return this . _colorAttachments [ 10 ] ; } get COLOR_ATTACHMENT11 ( ) : GLenum { return this . _colorAttachments [ 11 ] ; } get COLOR_ATTACHMENT12 ( ) : GLenum { return this . _colorAttachments [ 12 ] ; } get COLOR_ATTACHMENT13 ( ) : GLenum { return this . _colorAttachments [ 13 ] ; } get COLOR_ATTACHMENT14 ( ) : GLenum { return this . _colorAttachments [ 14 ] ; } get COLOR_ATTACHMENT15 ( ) : GLenum { return this . _colorAttachments [ 15 ] ; } /**
     * Queries the valid range of color attachments and provides an interface for convenience.
     */ protected queryColorAttachments ( context ) { const gl = context . gl ; this . _colorAttachments = new Array < GLenum > ( 16 ) ; this . _colorAttachments [ 0 ] = gl . COLOR_ATTACHMENT0 ; /**
         * In WebGL, draw buffers is supported by extension, in WebGL2 by default.
         * This maps the various default color attachment identifier to a unified interface.
         */ switch ( context . backend ) { case Context . BackendType . WebGL1 : const drawBuffers = context . supportsDrawBuffers ? context . drawBuffers : undefined ; this . _colorAttachmentMin = this . _colorAttachments [ 0 ] ; this . _colorAttachmentMax = this . _colorAttachmentMin + ( drawBuffers ? gl . getParameter ( drawBuffers . MAX_COLOR_ATTACHMENTS_WEBGL ) : 0 ) as GLenum ; this . _colorAttachments [ 0 ] = drawBuffers ? drawBuffers . COLOR_ATTACHMENT0_WEBGL : gl . COLOR_ATTACHMENT0 ; if ( ! drawBuffers ) { break ; } for ( let i = 1 ; i < 16 ; ++ i ) { this . _colorAttachments [ i ] = drawBuffers . COLOR_ATTACHMENT0_WEBGL + i ; } break ; case Context . BackendType . WebGL2 : default : this . _colorAttachmentMin = context . gl . COLOR_ATTACHMENT0 ; this . _colorAttachmentMax = context . gl . COLOR_ATTACHMENT0 + gl . getParameter ( gl . MAX_COLOR_ATTACHMENTS ) as GLenum ; for ( let i = 0 ; i < 16 ; ++ i ) { this . _colorAttachments [ i ] = gl . COLOR_ATTACHMENT0 + i ; } break ; } } link drawArraysInstanced : ( mode : GLenum , first : GLint , count : GLsizei , instanceCount : GLsizei ) => void ; link drawElementsInstanced : ( mode : GLenum , count : GLint , type : GLsizei , offset : GLintptr , primcount : GLsizei ) => void ; link vertexAttribDivisor : ( index : GLuint , divisor : GLuint ) => void ; param context protected queryInstancedArraySupport ( context ) { if ( ! context . isWebGL2 && ! context . supportsInstancedArrays ) { return ; } this . drawArraysInstanced = context . isWebGL2 ? ( mode , first , count , instanceCount ) => context . gl . drawArraysInstanced ( mode , first , count , instanceCount ) : ( mode , first , count , instanceCount ) => context . instancedArrays . drawArraysInstancedANGLE ( mode , first , count , instanceCount ) ; this . drawElementsInstanced = context . isWebGL2 ? ( mode , count , type , offset , primcount ) => context . gl . drawElementsInstanced ( mode , count , type , offset , primcount ) : ( mode , count , type , offset , primcount ) => context . instancedArrays . drawElementsInstancedANGLE ( mode , count , type , offset , primcount ) ; this . vertexAttribDivisor = context . isWebGL2 ? ( index , divisor ) => context . gl . vertexAttribDivisor ( index , divisor ) : ( index , divisor ) => context . instancedArrays . vertexAttribDivisorANGLE ( index , divisor ) ; } /**
     * Stores the MAX_DRAW_BUFFERS enum if supported. @see  MAX_DRAW_BUFFERS protected _maxDrawBuffers : GLenum ; /**
     * The MAX_DRAW_BUFFERS format enum. Is `undefined` if not supported.
     */ get MAX_DRAW_BUFFERS ( ) : GLenum { return this . _maxDrawBuffers ; } link drawBuffers : ( ( buffers : Array < GLenum > ) => void ) | undefined = undefined ; param context protected queryDrawBuffersSupport ( context ) { if ( ! context . isWebGL2 && ! context . supportsDrawBuffers ) { return ; } this . drawBuffers = context . isWebGL2 ? ( buffers ) => context . gl . drawBuffers ( buffers ) : ( buffers ) => context . drawBuffers . drawBuffersWEBGL ( buffers ) ; this . _maxDrawBuffers = context . isWebGL2 ? context . gl . MAX_DRAW_BUFFERS : context . drawBuffers . MAX_DRAW_BUFFERS_WEBGL ; } link createVertexArray : ( ) => any ; link deleteVertexArray : ( arrayObject : any ) => void ; link isVertexArray : ( arrayObject : any ) => GLboolean ; link bindVertexArray : ( arrayObject : any ) => void ; protected queryVertexArrayObjectSupport ( context ) { if ( ! context . isWebGL2 && ! context . supportsVertexArrayObject ) { return ; } this . createVertexArray = context . isWebGL2 ? ( ) => context . gl . createVertexArray ( ) : ( ) => context . vertexArrayObject . createVertexArrayOES ( ) ; this . deleteVertexArray = context . isWebGL2 ? ( arrayObject ) => context . gl . deleteVertexArray ( arrayObject ) : ( arrayObject ) => context . vertexArrayObject . deleteVertexArrayOES ( arrayObject ) ; this . isVertexArray = context . isWebGL2 ? ( arrayObject ) => context . gl . isVertexArray ( arrayObject ) : ( arrayObject ) => context . vertexArrayObject . isVertexArrayOES ( arrayObject ) ; this . bindVertexArray = context . isWebGL2 ? ( arrayObject ) => context . gl . bindVertexArray ( arrayObject ) : ( arrayObject ) => context . vertexArrayObject . bindVertexArrayOES ( arrayObject ) ; } see maxUniformVec3Components protected _maxUniformVec3Components : GLint | undefined ; /**
     * The maximum number of floats, integers, or booleans that can be in storage for a vertex shader.
     */ get maxUniformVec3Components ( ) : GLint | undefined { return this . _maxUniformVec3Components ; } param context protected queryMaxUniformVec3Components ( context ) { const gl = context . gl ; this . _maxUniformVec3Components = context . isWebGL2 ? gl . getParameter ( gl . MAX_VERTEX_UNIFORM_COMPONENTS ) : gl . getParameter ( gl . MAX_VERTEX_UNIFORM_VECTORS ) * 3 ; } link bufferSubData : ( target : GLenum , dstByteOffset : GLintptr , srcData : ArrayBufferView | ArrayBuffer , srcOffset : GLuint , length : GLuint ) => void ; protected queryBufferSubDataInterface ( context ) { const gl = context . gl ; if ( context . isWebGL2 ) { this . bufferSubData = ( target , dstByteOffset , srcData , srcOffset , length = 0 ) => { return gl . bufferSubData ( target , dstByteOffset , srcData , srcOffset , length ) ; } ; } else { this . bufferSubData = ( target , dstByteOffset , srcData , srcOffset = 0 , length = 0 ) => { logIf ( srcOffset !== 0 , LogLevel . Warning , `srcOffset ignored (not supported in WebGL)` ) ; logIf ( length !== 0 , LogLevel . Warning , `length ignored (not supported in WebGL)` ) ; return gl . bufferSubData ( target , dstByteOffset , srcData ) ; } ; } } link texImage2D : ( target : GLenum , level : GLint , internalformat : GLenum , width : GLsizei , height : GLsizei , border : GLint , format : GLenum , type : GLenum , source ? : TexImage2DData , offset ? : GLintptr ) => void ; link texImage3D : ( target : GLenum , level : GLint , internalformat : GLenum , width : GLsizei , height : GLsizei , depth : GLsizei , border : GLint , format : GLenum , type : GLenum , source ? : TexImage3DData , offset ? : GLintptr ) => void ; protected queryTexImageInterface ( context ) { const gl = context . gl ; if ( context . isWebGL2 ) { this . texImage2D = ( target , level , internalformat , width , height , border , format , type , source ? , offset ? ) => { if ( source instanceof ArrayBuffer ) { return gl . texImage2D ( target , level , internalformat , width , height , border , format , type , source === undefined ? null : source , offset ) ; } assert ( offset === undefined , `offset expected to be undefined for non ArrayBuffer source` ) ; return gl . texImage2D ( target , level , internalformat , width , height , border , format , type , source === undefined ? null : source ) ; } ; } else { this . texImage2D = ( target , level , internalformat , width , height , border , format , type , source ? , offset ? ) => { if ( source === undefined ) { return gl . texImage2D ( target , level , internalformat , width , height , border , format , type , null ) ; } if ( source instanceof Int8Array || source instanceof Uint8Array || source instanceof Uint8ClampedArray || source instanceof Int16Array || source instanceof Uint16Array || source instanceof Int32Array || source instanceof Uint32Array || source instanceof Float32Array || source instanceof Float64Array || source instanceof DataView ) { return gl . texImage2D ( target , level , internalformat , width , height , border , format , type , source ) ; } return gl . texImage2D ( target , level , internalformat , format , type , source ) ; } ; } if ( context . supportsTexImage3D ) { this . texImage3D = ( target , level , internalformat , width , height , depth , border , format , type , source ? , offset ? ) => { if ( source instanceof ArrayBuffer ) { return gl . texImage3D ( target , level , internalformat , width , height , depth , border , format , type , source === undefined ? null : source , offset ) ; } assert ( offset === undefined , `offset expected to be undefined for non ArrayBuffer source` ) ; return gl . texImage3D ( target , level , internalformat , width , height , depth , border , format , type , source === undefined ? null : source ) ; } ; } else { this . texImage3D = ( target , level , internalformat , width , height , depth , border , format , type , source ? , offset ? ) => assert ( false , 'texImage3D not supported on this context' ) ; } } }