From 9e3c84192850edf22e99e7c148b2e524aba7366d Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 19 Dec 2023 12:20:08 -0800 Subject: [PATCH] Include GL extension fliter/allowlist if and only if its needed Here we use the JS library dependency mechanism to include this code only when its needed. Sadly this will end up being preset in almost all GL-using programs because most of them will end up using `emscriptenWebGLGet` (e.g. any app that calls `glGetInteger`, `glGetString`, etc) Fixes: #20798 --- src/library_glemu.js | 12 ++- src/library_glew.js | 4 +- src/library_glfw.js | 4 +- src/library_html5_webgl.js | 3 + src/library_webgl.js | 146 ++++++++++++++++++------------------- src/library_webgl2.js | 4 +- 6 files changed, 88 insertions(+), 85 deletions(-) diff --git a/src/library_glemu.js b/src/library_glemu.js index 51cf48fa57c46..3e439ec7aa497 100644 --- a/src/library_glemu.js +++ b/src/library_glemu.js @@ -6,7 +6,15 @@ var LibraryGLEmulation = { // GL emulation: provides misc. functionality not present in OpenGL ES 2.0 or WebGL - $GLEmulation__deps: ['$GLImmediateSetup', 'glEnable', 'glDisable', 'glIsEnabled', 'glGetBooleanv', 'glGetIntegerv', 'glGetString', 'glCreateShader', 'glShaderSource', 'glCompileShader', 'glAttachShader', 'glDetachShader', 'glUseProgram', 'glDeleteProgram', 'glBindAttribLocation', 'glLinkProgram', 'glBindBuffer', 'glGetFloatv', 'glHint', 'glEnableVertexAttribArray', 'glDisableVertexAttribArray', 'glVertexAttribPointer', 'glActiveTexture', '$stringToNewUTF8', '$ptrToString'], + $GLEmulation__deps: ['$GLImmediateSetup', 'glEnable', 'glDisable', + 'glIsEnabled', 'glGetBooleanv', 'glGetIntegerv', 'glGetString', + 'glCreateShader', 'glShaderSource', 'glCompileShader', 'glAttachShader', + 'glDetachShader', 'glUseProgram', 'glDeleteProgram', 'glBindAttribLocation', + 'glLinkProgram', 'glBindBuffer', 'glGetFloatv', 'glHint', + 'glEnableVertexAttribArray', 'glDisableVertexAttribArray', + 'glVertexAttribPointer', 'glActiveTexture', '$stringToNewUTF8', + '$ptrToString', '$getEmscriptenSupportedExtensions', + ], $GLEmulation__postset: #if MAYBE_CLOSURE_COMPILER // Forward declare GL functions that are overridden by GLEmulation here to appease Closure compiler. @@ -394,7 +402,7 @@ var LibraryGLEmulation = { if (GL.stringCache[name_]) return GL.stringCache[name_]; switch (name_) { case 0x1F03 /* GL_EXTENSIONS */: // Add various extensions that we can support - var ret = stringToNewUTF8((GLctx.getSupportedExtensions() || []).join(' ') + + var ret = stringToNewUTF8(getEmscriptenSupportedExtensions(GLctx).join(' ') + ' GL_EXT_texture_env_combine GL_ARB_texture_env_crossbar GL_ATI_texture_env_combine3 GL_NV_texture_env_combine4 GL_EXT_texture_env_dot3 GL_ARB_multitexture GL_ARB_vertex_buffer_object GL_EXT_framebuffer_object GL_ARB_vertex_program GL_ARB_fragment_program GL_ARB_shading_language_100 GL_ARB_shader_objects GL_ARB_vertex_shader GL_ARB_fragment_shader GL_ARB_texture_cube_map GL_EXT_draw_range_elements' + (GL.currentContext.compressionExt ? ' GL_ARB_texture_compression GL_EXT_texture_compression_s3tc' : '') + (GL.currentContext.anisotropicExt ? ' GL_EXT_texture_filter_anisotropic' : '') diff --git a/src/library_glew.js b/src/library_glew.js index 0c03085c3d8a3..9af8a494076a2 100644 --- a/src/library_glew.js +++ b/src/library_glew.js @@ -20,7 +20,7 @@ */ var LibraryGLEW = { - $GLEW__deps: ['glGetString', '$stringToNewUTF8', '$UTF8ToString'], + $GLEW__deps: ['glGetString', '$stringToNewUTF8', '$UTF8ToString', '$webglGetExtensions'], $GLEW: { isLinaroFork: 1, extensions: null, @@ -99,7 +99,7 @@ var LibraryGLEW = { }, extensionIsSupported(name) { - GLEW.extensions ||= GL.getExtensions(); + GLEW.extensions ||= webglGetExtensions(); if (GLEW.extensions.includes(name)) return 1; diff --git a/src/library_glfw.js b/src/library_glfw.js index 93e0331fe56b6..019f9da6d809f 100644 --- a/src/library_glfw.js +++ b/src/library_glfw.js @@ -1468,9 +1468,9 @@ var LibraryGLFW = { GLFW.initialTime = GLFW.getTime() - time; }, - glfwExtensionSupported__deps: ['glGetString'], + glfwExtensionSupported__deps: ['glGetString', 'webglGetExtensions'], glfwExtensionSupported: (extension) => { - GLFW.extensions ||= GL.getExtensions(); + GLFW.extensions ||= webglGetExtensions(); if (GLFW.extensions.includes(extension)) return 1; diff --git a/src/library_html5_webgl.js b/src/library_html5_webgl.js index c0e984bc4dd62..468fe487c6423 100644 --- a/src/library_html5_webgl.js +++ b/src/library_html5_webgl.js @@ -440,6 +440,9 @@ var LibraryHtml5WebGL = { emscripten_webgl_get_supported_extensions__proxy: 'sync_on_current_webgl_context_thread', emscripten_webgl_get_supported_extensions__deps: ['$stringToNewUTF8'], + // Here we report the full list of extensions supported by WebGL rather than + // using getEmscriptenSupportedExtensions which filters the list based on + // what is has explicit support in. emscripten_webgl_get_supported_extensions: () => stringToNewUTF8(GLctx.getSupportedExtensions().join(' ')), diff --git a/src/library_webgl.js b/src/library_webgl.js index 2096d85d59543..886ee6c353dfd 100644 --- a/src/library_webgl.js +++ b/src/library_webgl.js @@ -135,6 +135,56 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; emscripten_webgl_enable_WEBGL_multi_draw__deps: ['$webgl_enable_WEBGL_multi_draw'], emscripten_webgl_enable_WEBGL_multi_draw: (ctx) => webgl_enable_WEBGL_multi_draw(GL.contexts[ctx].GLctx), + $getEmscriptenSupportedExtensions__internal: true, + $getEmscriptenSupportedExtensions: function(ctx) { + // Restrict the list of advertised extensions to those that we actually + // support. + var supportedExtensions = [ +#if MIN_WEBGL_VERSION == 1 + // WebGL 1 extensions + 'ANGLE_instanced_arrays', + 'EXT_blend_minmax', + 'EXT_disjoint_timer_query', + 'EXT_frag_depth', + 'EXT_shader_texture_lod', + 'EXT_sRGB', + 'OES_element_index_uint', + 'OES_fbo_render_mipmap', + 'OES_standard_derivatives', + 'OES_texture_float', + 'OES_texture_half_float', + 'OES_texture_half_float_linear', + 'OES_vertex_array_object', + 'WEBGL_color_buffer_float', + 'WEBGL_depth_texture', + 'WEBGL_draw_buffers', +#endif +#if MAX_WEBGL_VERSION >= 2 + // WebGL 2 extensions + 'EXT_color_buffer_float', + 'EXT_disjoint_timer_query_webgl2', + 'EXT_texture_norm16', + 'WEBGL_clip_cull_distance', +#endif + // WebGL 1 and WebGL 2 extensions + 'EXT_color_buffer_half_float', + 'EXT_float_blend', + 'EXT_texture_compression_bptc', + 'EXT_texture_compression_rgtc', + 'EXT_texture_filter_anisotropic', + 'KHR_parallel_shader_compile', + 'OES_texture_float_linear', + 'WEBGL_compressed_texture_s3tc', + 'WEBGL_compressed_texture_s3tc_srgb', + 'WEBGL_debug_renderer_info', + 'WEBGL_debug_shaders', + 'WEBGL_lose_context', + 'WEBGL_multi_draw', + ]; + // .getSupportedExtensions() can return null if context is lost, so coerce to empty array. + return (ctx.getSupportedExtensions() || []).filter(ext => supportedExtensions.includes(ext)); + }, + $GL__postset: 'var GLctx;', #if GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS // If GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS is enabled, GL.initExtensions() will call to initialize these. @@ -153,8 +203,9 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; '$webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance', #endif '$webgl_enable_WEBGL_multi_draw', + '$getEmscriptenSupportedExtensions', ], -#endif +#endif // GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS $GL: { #if GL_DEBUG debug: true, @@ -738,60 +789,6 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; } disableHalfFloatExtensionIfBroken(ctx); #endif - - // If end user enables *glGetProcAddress() functionality or - // GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS, then we must filter out - // all future WebGL extensions from being passed to the user, and only restrict to advertising - // extensions that the *glGetProcAddress() function knows to handle. -#if GL_ENABLE_GET_PROC_ADDRESS || GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS - var _allSupportedExtensions = ctx.getSupportedExtensions; - var supportedExtensionsForGetProcAddress = [ -#if MIN_WEBGL_VERSION == 1 - // WebGL 1 extensions - 'ANGLE_instanced_arrays', - 'EXT_blend_minmax', - 'EXT_disjoint_timer_query', - 'EXT_frag_depth', - 'EXT_shader_texture_lod', - 'EXT_sRGB', - 'OES_element_index_uint', - 'OES_fbo_render_mipmap', - 'OES_standard_derivatives', - 'OES_texture_float', - 'OES_texture_half_float', - 'OES_texture_half_float_linear', - 'OES_vertex_array_object', - 'WEBGL_color_buffer_float', - 'WEBGL_depth_texture', - 'WEBGL_draw_buffers', -#endif -#if MAX_WEBGL_VERSION >= 2 - // WebGL 2 extensions - 'EXT_color_buffer_float', - 'EXT_disjoint_timer_query_webgl2', - 'EXT_texture_norm16', - 'WEBGL_clip_cull_distance', -#endif - // WebGL 1 and WebGL 2 extensions - 'EXT_color_buffer_half_float', - 'EXT_float_blend', - 'EXT_texture_compression_bptc', - 'EXT_texture_compression_rgtc', - 'EXT_texture_filter_anisotropic', - 'KHR_parallel_shader_compile', - 'OES_texture_float_linear', - 'WEBGL_compressed_texture_s3tc', - 'WEBGL_compressed_texture_s3tc_srgb', - 'WEBGL_debug_renderer_info', - 'WEBGL_debug_shaders', - 'WEBGL_lose_context', - 'WEBGL_multi_draw', - ]; - ctx.getSupportedExtensions = function() { - return (_allSupportedExtensions.apply(this) || []).filter(ext => supportedExtensionsForGetProcAddress.includes(ext)); - } -#endif - return handle; }, @@ -1206,10 +1203,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; webgl_enable_WEBGL_multi_draw(GLctx); - // .getSupportedExtensions() can return null if context is lost, so coerce - // to empty array. - var exts = GLctx.getSupportedExtensions() || []; - exts.forEach((ext) => { + getEmscriptenSupportedExtensions(GLctx).forEach((ext) => { // WEBGL_lose_context, WEBGL_debug_renderer_info and WEBGL_debug_shaders // are not enabled by default. if (!ext.includes('lose_context') && !ext.includes('debug')) { @@ -1220,14 +1214,16 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; }, #endif - getExtensions() { - // .getSupportedExtensions() can return null if context is lost, so coerce to empty array. - var exts = GLctx.getSupportedExtensions() || []; + }, + + $webglGetExtensions__internal: true, + $webglGetExtensions__deps: ['$getEmscriptenSupportedExtensions'], + $webglGetExtensions() { + var exts = getEmscriptenSupportedExtensions(GLctx); #if GL_EXTENSIONS_IN_PREFIXED_FORMAT - exts = exts.concat(exts.map((e) => "GL_" + e)); + exts = exts.concat(exts.map((e) => "GL_" + e)); #endif - return exts; - }, + return exts; }, glPixelStorei: (pname, param) => { @@ -1237,13 +1233,13 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; GLctx.pixelStorei(pname, param); }, - glGetString__deps: ['$stringToNewUTF8'], + glGetString__deps: ['$stringToNewUTF8', '$webglGetExtensions'], glGetString: (name_) => { var ret = GL.stringCache[name_]; if (!ret) { switch (name_) { case 0x1F03 /* GL_EXTENSIONS */: - ret = stringToNewUTF8(GL.getExtensions().join(' ')); + ret = stringToNewUTF8(webglGetExtensions().join(' ')); break; case 0x1F00 /* GL_VENDOR */: case 0x1F01 /* GL_RENDERER */: @@ -1305,7 +1301,11 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; return ret; }, - $emscriptenWebGLGet__deps: ['$writeI53ToI64'], + $emscriptenWebGLGet__deps: ['$writeI53ToI64', +#if MAX_WEBGL_VERSION >= 2 + '$webglGetExtensions', // For GL_NUM_EXTENSIONS +#endif + ], $emscriptenWebGLGet: (name_, p, type) => { // Guard against user passing a null pointer. // Note that GLES2 spec does not say anything about how passing a null @@ -1368,15 +1368,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; return; } #endif - // .getSupportedExtensions() can return null if context is lost, so coerce to empty array. - var exts = GLctx.getSupportedExtensions() || []; -#if GL_EXTENSIONS_IN_PREFIXED_FORMAT - // each extension is duplicated, first in unprefixed WebGL form, and - // then a second time with "GL_" prefix. - ret = 2 * exts.length; -#else - ret = exts.length; -#endif + ret = webglGetExtensions().length; break; case 0x821B: // GL_MAJOR_VERSION case 0x821C: // GL_MINOR_VERSION diff --git a/src/library_webgl2.js b/src/library_webgl2.js index 02ebd29069cf7..93e16b4ed3049 100644 --- a/src/library_webgl2.js +++ b/src/library_webgl2.js @@ -5,7 +5,7 @@ */ var LibraryWebGL2 = { - glGetStringi__deps: ['$stringToNewUTF8'], + glGetStringi__deps: ['$webglGetExtensions', '$stringToNewUTF8'], glGetStringi: (name, index) => { if (GL.currentContext.version < 2) { GL.recordError(0x502 /* GL_INVALID_OPERATION */); // Calling GLES3/WebGL2 function with a GLES2/WebGL1 context @@ -24,7 +24,7 @@ var LibraryWebGL2 = { } switch (name) { case 0x1F03 /* GL_EXTENSIONS */: - var exts = GL.getExtensions().map(stringToNewUTF8); + var exts = webglGetExtensions().map(stringToNewUTF8); stringiCache = GL.stringiCache[name] = exts; if (index < 0 || index >= stringiCache.length) { GL.recordError(0x501/*GL_INVALID_VALUE*/);