From 5ee269fac2ba48e6d463d9fa06baecce7d17d895 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 | 4 +- src/library_webgl.js | 131 +++++++++++++++++++------------------ src/library_webgl2.js | 4 +- 6 files changed, 84 insertions(+), 75 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..e1058b90f3dff 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', '$glGetExtensions'], $GLEW: { isLinaroFork: 1, extensions: null, @@ -99,7 +99,7 @@ var LibraryGLEW = { }, extensionIsSupported(name) { - GLEW.extensions ||= GL.getExtensions(); + GLEW.extensions ||= glGetExtensions(); if (GLEW.extensions.includes(name)) return 1; diff --git a/src/library_glfw.js b/src/library_glfw.js index ebdca229efd23..88d8c1ed880c5 100644 --- a/src/library_glfw.js +++ b/src/library_glfw.js @@ -1467,9 +1467,9 @@ var LibraryGLFW = { GLFW.initialTime = GLFW.getTime() - time; }, - glfwExtensionSupported__deps: ['glGetString'], + glfwExtensionSupported__deps: ['glGetString', 'glGetExtensions'], glfwExtensionSupported: (extension) => { - GLFW.extensions ||= GL.getExtensions(); + GLFW.extensions ||= glGetExtensions(); if (GLFW.extensions.includes(extension)) return 1; diff --git a/src/library_html5_webgl.js b/src/library_html5_webgl.js index c0e984bc4dd62..c4453bfae41de 100644 --- a/src/library_html5_webgl.js +++ b/src/library_html5_webgl.js @@ -439,9 +439,9 @@ var LibraryHtml5WebGL = { }, emscripten_webgl_get_supported_extensions__proxy: 'sync_on_current_webgl_context_thread', - emscripten_webgl_get_supported_extensions__deps: ['$stringToNewUTF8'], + emscripten_webgl_get_supported_extensions__deps: ['$stringToNewUTF8', '$getEmscriptenSupportedExtensions'], emscripten_webgl_get_supported_extensions: () => - stringToNewUTF8(GLctx.getSupportedExtensions().join(' ')), + stringToNewUTF8(getEmscriptenSupportedExtensions(GLctx).join(' ')), emscripten_webgl_get_program_parameter_d__proxy: 'sync_on_current_webgl_context_thread', emscripten_webgl_get_program_parameter_d: (program, param) => diff --git a/src/library_webgl.js b/src/library_webgl.js index 2096d85d59543..8c79d8babd9fa 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 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', + ]; + // .getSupportedExtensions() can return null if context is lost, so coerce to empty array. + return (ctx.getSupportedExtensions() || []).filter(ext => supportedExtensionsForGetProcAddress.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. @@ -738,60 +788,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; }, @@ -1220,14 +1216,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() || []; + }, + + $glGetExtensions__internal: true, + $glGetExtensions__deps: ['$getEmscriptenSupportedExtensions'], + $glGetExtensions() { + 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 +1235,13 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; GLctx.pixelStorei(pname, param); }, - glGetString__deps: ['$stringToNewUTF8'], + glGetString__deps: ['$stringToNewUTF8', '$glGetExtensions'], glGetString: (name_) => { var ret = GL.stringCache[name_]; if (!ret) { switch (name_) { case 0x1F03 /* GL_EXTENSIONS */: - ret = stringToNewUTF8(GL.getExtensions().join(' ')); + ret = stringToNewUTF8(glGetExtensions().join(' ')); break; case 0x1F00 /* GL_VENDOR */: case 0x1F01 /* GL_RENDERER */: @@ -1305,7 +1303,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 + '$getEmscriptenSupportedExtensions' +#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,8 +1370,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() || []; + var exts = getEmscriptenSupportedExtensions(GLctx); #if GL_EXTENSIONS_IN_PREFIXED_FORMAT // each extension is duplicated, first in unprefixed WebGL form, and // then a second time with "GL_" prefix. diff --git a/src/library_webgl2.js b/src/library_webgl2.js index c972f726c3a1e..aecfc05077483 100644 --- a/src/library_webgl2.js +++ b/src/library_webgl2.js @@ -5,7 +5,7 @@ */ var LibraryWebGL2 = { - glGetStringi__deps: ['$stringToNewUTF8'], + glGetStringi__deps: ['$glGetExtensions', '$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((e) => stringToNewUTF8(e)); + var exts = glGetExtensions().map((e) => stringToNewUTF8(e)); stringiCache = GL.stringiCache[name] = exts; if (index < 0 || index >= stringiCache.length) { GL.recordError(0x501/*GL_INVALID_VALUE*/);