UNPKG

@cornerstonejs/core

Version:
146 lines (142 loc) 4.92 kB
const canvasSize = 4; const texWidth = 5; const texHeight = 1; const pixelToCheck = [1, 1]; function createProbeContext() { try { const canvas = document.createElement('canvas'); canvas.width = canvasSize; canvas.height = canvasSize; const gl = canvas.getContext('webgl2'); if (!gl) { return null; } const vs = `#version 300 es void main() { gl_PointSize = ${canvasSize.toFixed(1)}; gl_Position = vec4(0, 0, 0, 1); } `; const fs = `#version 300 es precision highp float; precision highp int; precision highp sampler2D; uniform sampler2D u_image; out vec4 color; void main() { vec4 intColor = texture(u_image, gl_PointCoord.xy); color = vec4(vec3(intColor.rrr), 1); } `; const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vs); gl.compileShader(vertexShader); if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { return null; } const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fs); gl.compileShader(fragmentShader); if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { return null; } const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { return null; } gl.useProgram(program); return gl; } catch (e) { return null; } } function probeFormat(gl, { ext, filterType, texData, internalFormat, glDataType }) { try { let extToUse; if (ext) { extToUse = gl.getExtension(ext); if (!extToUse) { return false; } } const tex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex); gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat(gl, extToUse), texWidth, texHeight, 0, gl.RED, glDataType(gl, extToUse), texData); const filter = filterType === 'LINEAR' ? gl.LINEAR : gl.NEAREST; gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter); gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.POINTS, 0, 1); const pixel = new Uint8Array(4); gl.readPixels(pixelToCheck[0], pixelToCheck[1], 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); const [r, g, b] = pixel; gl.deleteTexture(tex); return r === g && g === b && r !== 0; } catch (e) { return false; } } export function getSupportedTextureFormats() { const gl = createProbeContext(); if (!gl) { return null; } const norm16TexData = new Int16Array([ 32767, 2000, 3000, 4000, 5000, 16784, 7000, 8000, 9000, 32767, ]); const floatTexData = new Float32Array([0.3, 0.2, 0.3, 0.4, 0.5]); const halfFloatTexData = new Uint16Array([13517, 12902, 13517, 13926, 14336]); const result = { norm16: probeFormat(gl, { ext: 'EXT_texture_norm16', filterType: 'NEAREST', texData: norm16TexData, internalFormat: (_gl, ext) => ext.R16_SNORM_EXT, glDataType: (_gl) => _gl.SHORT, }), norm16Linear: probeFormat(gl, { ext: 'EXT_texture_norm16', filterType: 'LINEAR', texData: norm16TexData, internalFormat: (_gl, ext) => ext.R16_SNORM_EXT, glDataType: (_gl) => _gl.SHORT, }), float: probeFormat(gl, { filterType: 'NEAREST', texData: floatTexData, internalFormat: (_gl) => _gl.R32F, glDataType: (_gl) => _gl.FLOAT, }), floatLinear: probeFormat(gl, { ext: 'OES_texture_float_linear', filterType: 'LINEAR', texData: floatTexData, internalFormat: (_gl) => _gl.R32F, glDataType: (_gl) => _gl.FLOAT, }), halfFloat: probeFormat(gl, { filterType: 'NEAREST', texData: halfFloatTexData, internalFormat: (_gl) => _gl.R16F, glDataType: (_gl) => _gl.HALF_FLOAT, }), halfFloatLinear: probeFormat(gl, { filterType: 'LINEAR', texData: halfFloatTexData, internalFormat: (_gl) => _gl.R16F, glDataType: (_gl) => _gl.HALF_FLOAT, }), }; const contextLost = gl.isContextLost(); const webglLoseContext = gl.getExtension('WEBGL_lose_context'); if (webglLoseContext) { webglLoseContext.loseContext(); } return contextLost ? null : result; }