Skip to content

Commit

Permalink
Include GL extension fliter/allowlist if and only if its needed
Browse files Browse the repository at this point in the history
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: emscripten-core#20798
  • Loading branch information
sbc100 committed Dec 20, 2023
1 parent 9f19a52 commit 5ee269f
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 75 deletions.
12 changes: 10 additions & 2 deletions src/library_glemu.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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' : '')
Expand Down
4 changes: 2 additions & 2 deletions src/library_glew.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*/

var LibraryGLEW = {
$GLEW__deps: ['glGetString', '$stringToNewUTF8', '$UTF8ToString'],
$GLEW__deps: ['glGetString', '$stringToNewUTF8', '$UTF8ToString', '$glGetExtensions'],
$GLEW: {
isLinaroFork: 1,
extensions: null,
Expand Down Expand Up @@ -99,7 +99,7 @@ var LibraryGLEW = {
},

extensionIsSupported(name) {
GLEW.extensions ||= GL.getExtensions();
GLEW.extensions ||= glGetExtensions();

if (GLEW.extensions.includes(name))
return 1;
Expand Down
4 changes: 2 additions & 2 deletions src/library_glfw.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions src/library_html5_webgl.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand Down
131 changes: 66 additions & 65 deletions src/library_webgl.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
},

Expand Down Expand Up @@ -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) => {
Expand All @@ -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 */:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions src/library_webgl2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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*/);
Expand Down

0 comments on commit 5ee269f

Please sign in to comment.