Skip to content

Commit 4658b0e

Browse files
committed
Gate *glGetProcAddress() functions behind a linker flag -sGL_ENABLE_GET_PROC_ADDRESS=1 so that we can restrict new GL extensions from being advertised in the future that *glGetProcAddress() cannot support.
1 parent 9de528b commit 4658b0e

File tree

16 files changed

+155
-26
lines changed

16 files changed

+155
-26
lines changed

ChangeLog.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ See docs/process.md for more on how version tagging works.
4545
- Update GLFW handling of touch events to avoid sending duplicate mousedown and
4646
and mouseup events. Maps touchmove to mousemove events for a single primary
4747
touch. (#20805)
48+
- Breaking change: Using the `*glGetProcAddress()` family of functions now
49+
requires passing a linker flag -sGL_ENABLE_GET_PROC_ADDRESS. This prevents
50+
ports of native GL renderers from later accidentally attempting to activate
51+
"dormant" features if web browser implementations gain new WebGL extensions in
52+
the future, which `*glGetProcAddress()` is not able to support. (#20802)
4853

4954
3.1.49 - 11/14/23
5055
-----------------

embuilder.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
'libmimalloc',
6060
'libmimalloc-mt',
6161
'libGL',
62+
'libGL-getprocaddr',
6263
'libhtml5',
6364
'libsockets',
6465
'libstubs',

emcc.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,11 @@ def phase_setup(options, state, newargs):
935935
else:
936936
settings.SUPPORT_LONGJMP = 'emscripten'
937937

938+
# SDL2 requires eglGetProcAddress() to work.
939+
# NOTE: if SDL2 is updated to not rely on eglGetProcAddress(), this can be removed
940+
if settings.USE_SDL == 2 or settings.USE_SDL_MIXER == 2 or settings.USE_SDL_GFX == 2:
941+
default_setting('GL_ENABLE_GET_PROC_ADDRESS', 1)
942+
938943
return (newargs, input_files)
939944

940945

src/library_exceptions_stub.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ var LibraryExceptions = {};
2222
].forEach(function(name) {
2323
LibraryExceptions[name] = function() { abort(); };
2424
#if !INCLUDE_FULL_LIBRARY
25-
// This method of link-time error genertation is not compatible with INCLUDE_FULL_LIBRARY
25+
// This method of link-time error generation is not compatible with INCLUDE_FULL_LIBRARY
2626
LibraryExceptions[name + '__deps'] = [function() {
2727
error(`DISABLE_EXCEPTION_THROWING was set (likely due to -fno-exceptions), which means no C++ exception throwing support code is linked in, but such support is required by symbol '${name}'. Either do not set DISABLE_EXCEPTION_THROWING (if you do want exception throwing) or compile all source files with -fno-except (so that no exceptions support code is required); also make sure DISABLE_EXCEPTION_CATCHING is set to the right value - if you want exceptions, it should be off, and vice versa.`);
2828
}];

src/library_sigs.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ sigs = {
7676
SDL_GL_DeleteContext__sig: 'vp',
7777
SDL_GL_ExtensionSupported__sig: 'ip',
7878
SDL_GL_GetAttribute__sig: 'iip',
79+
SDL_GL_GetProcAddress__sig: 'pp',
7980
SDL_GL_GetSwapInterval__sig: 'i',
8081
SDL_GL_MakeCurrent__sig: 'ipp',
8182
SDL_GL_SetAttribute__sig: 'iii',
@@ -547,6 +548,7 @@ sigs = {
547548
eglGetCurrentSurface__sig: 'pi',
548549
eglGetDisplay__sig: 'pp',
549550
eglGetError__sig: 'i',
551+
eglGetProcAddress__sig: 'pp',
550552
eglInitialize__sig: 'ippp',
551553
eglMakeCurrent__sig: 'ipppp',
552554
eglQueryAPI__sig: 'i',
@@ -849,6 +851,8 @@ sigs = {
849851
emscripten_wasm_worker_post_function_vii__sig: 'vipii',
850852
emscripten_wasm_worker_post_function_viii__sig: 'vipiii',
851853
emscripten_wasm_worker_self_id__sig: 'i',
854+
emscripten_webgl1_get_proc_address__sig: 'pp',
855+
emscripten_webgl2_get_proc_address__sig: 'pp',
852856
emscripten_webgl_commit_frame__sig: 'i',
853857
emscripten_webgl_create_context__sig: 'ppp',
854858
emscripten_webgl_destroy_context__sig: 'ip',
@@ -870,6 +874,7 @@ sigs = {
870874
emscripten_webgl_get_parameter_o__sig: 'ii',
871875
emscripten_webgl_get_parameter_utf8__sig: 'pi',
872876
emscripten_webgl_get_parameter_v__sig: 'iipii',
877+
emscripten_webgl_get_proc_address__sig: 'pp',
873878
emscripten_webgl_get_program_info_log_utf8__sig: 'pi',
874879
emscripten_webgl_get_program_parameter_d__sig: 'dii',
875880
emscripten_webgl_get_shader_info_log_utf8__sig: 'pi',
@@ -1387,6 +1392,7 @@ sigs = {
13871392
glfwGetMouseWheel__sig: 'i',
13881393
glfwGetNumberOfProcessors__sig: 'i',
13891394
glfwGetPrimaryMonitor__sig: 'p',
1395+
glfwGetProcAddress__sig: 'pp',
13901396
glfwGetRequiredInstanceExtensions__sig: 'pp',
13911397
glfwGetThreadID__sig: 'i',
13921398
glfwGetTime__sig: 'd',

src/library_webgl.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,58 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}};
739739
disableHalfFloatExtensionIfBroken(ctx);
740740
#endif
741741

742+
// If end user enables *glGetProcAddress() functionality, then we must filter out
743+
// all future WebGL extensions from being passed to the user, and only restrict to advertising
744+
// extensions that the *glGetProcAddress() function knows to handle.
745+
#if GL_ENABLE_GET_PROC_ADDRESS
746+
var _allSupportedExtensions = ctx.getSupportedExtensions;
747+
var supportedExtensionsForGetProcAddress = [
748+
#if MIN_WEBGL_VERSION == 1
749+
// WebGL 1 extensions
750+
'ANGLE_instanced_arrays',
751+
'EXT_blend_minmax',
752+
'EXT_disjoint_timer_query',
753+
'EXT_frag_depth',
754+
'EXT_shader_texture_lod',
755+
'EXT_sRGB',
756+
'OES_element_index_uint',
757+
'OES_fbo_render_mipmap',
758+
'OES_standard_derivatives',
759+
'OES_texture_float',
760+
'OES_texture_half_float',
761+
'OES_texture_half_float_linear',
762+
'OES_vertex_array_object',
763+
'WEBGL_color_buffer_float',
764+
'WEBGL_depth_texture',
765+
'WEBGL_draw_buffers',
766+
#endif
767+
#if MAX_WEBGL_VERSION >= 2
768+
// WebGL 2 extensions
769+
'EXT_color_buffer_float',
770+
'EXT_disjoint_timer_query_webgl2',
771+
'EXT_texture_norm16',
772+
'WEBGL_clip_cull_distance',
773+
#endif
774+
// WebGL 1 and WebGL 2 extensions
775+
'EXT_color_buffer_half_float',
776+
'EXT_float_blend',
777+
'EXT_texture_compression_bptc',
778+
'EXT_texture_compression_rgtc',
779+
'EXT_texture_filter_anisotropic',
780+
'KHR_parallel_shader_compile',
781+
'OES_texture_float_linear',
782+
'WEBGL_compressed_texture_s3tc',
783+
'WEBGL_compressed_texture_s3tc_srgb',
784+
'WEBGL_debug_renderer_info',
785+
'WEBGL_debug_shaders',
786+
'WEBGL_lose_context',
787+
'WEBGL_multi_draw',
788+
];
789+
ctx.getSupportedExtensions = function() {
790+
return (_allSupportedExtensions.apply(this) || []).filter(ext => supportedExtensionsForGetProcAddress.includes(ext));
791+
}
792+
#endif
793+
742794
return handle;
743795
},
744796

@@ -4219,6 +4271,27 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}};
42194271
#endif
42204272
};
42214273

4274+
#if !GL_ENABLE_GET_PROC_ADDRESS
4275+
[
4276+
'emscripten_webgl1_get_proc_address',
4277+
'emscripten_webgl2_get_proc_address',
4278+
'emscripten_webgl_get_proc_address',
4279+
'SDL_GL_GetProcAddress',
4280+
'eglGetProcAddress',
4281+
'glfwGetProcAddress'
4282+
].forEach(function(name) {
4283+
LibraryGL[name] = function(name) { abort(); };
4284+
// Due to the two pass nature of compiling .js files,
4285+
// in INCLUDE_FULL_LIBRARY mode, we must include the above
4286+
// stub functions, but not their __deps message handlers.
4287+
#if !INCLUDE_FULL_LIBRARY
4288+
LibraryGL[name + '__deps'] = [function() {
4289+
error(`linker: Undefined symbol: ${name}(). Please pass -sGL_ENABLE_GET_PROC_ADDRESS at link time to link in ${name}().`);
4290+
}];
4291+
#endif
4292+
});
4293+
#endif
4294+
42224295
// Simple pass-through functions.
42234296
// - Starred ones have return values.
42244297
// - [X] ones have X in the C name but not in the JS name

src/settings.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,13 @@ var GL_DISABLE_HALF_FLOAT_EXTENSION_IF_BROKEN = false;
589589
// Set this to 0 to force-disable the workaround if you know the issue will not affect you.
590590
var GL_WORKAROUND_SAFARI_GETCONTEXT_BUG = true;
591591

592+
// If 1, link with support to *glGetProcAddress() functionality.
593+
// In WebGL, *glGetProcAddress() causes a substantial code size and performance impact, since WebGL
594+
// does not natively provide such functionality, and it must be emulated. Using *glGetProcAddress()
595+
// is not recommended. If you still need to use this, e.g. when porting an existing renderer,
596+
// you can link with -sGL_ENABLE_GET_PROC_ADDRESS=1 to get support for this functionality.
597+
var GL_ENABLE_GET_PROC_ADDRESS = false;
598+
592599
// Use JavaScript math functions like Math.tan. This saves code size as we can avoid shipping
593600
// compiled musl code. However, it can be significantly slower as it calls out to JS. It
594601
// also may give different results as JS math is specced somewhat differently than libc, and

system/lib/gl/gl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,6 +1569,8 @@ GLAPI void APIENTRY emscripten_glGetObjectParameteriv (GLhandleARB obj, GLenum p
15691569
GLAPI void APIENTRY emscripten_glGetInfoLog (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
15701570
GLAPI void APIENTRY emscripten_glBindProgram (GLenum target, GLuint program);
15711571

1572+
#if GL_ENABLE_GET_PROC_ADDRESS
1573+
15721574
extern void *emscripten_webgl1_get_proc_address(const char *name);
15731575
extern void *_webgl1_match_ext_proc_address_without_suffix(const char *name);
15741576
extern void *emscripten_webgl2_get_proc_address(const char *name);
@@ -1837,3 +1839,5 @@ extern void *emscripten_webgl_get_proc_address(const char *name)
18371839
#endif
18381840
return ptr;
18391841
}
1842+
1843+
#endif

system/lib/gl/libprocaddr.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
// GL proc address library integration
99

10+
#if GL_ENABLE_GET_PROC_ADDRESS
11+
1012
extern void* emscripten_GetProcAddress(const char *name);
1113

1214
__attribute__((weak)) // SDL2 will link in its own version of this
@@ -21,3 +23,5 @@ void* eglGetProcAddress(const char* name) {
2123
void* glfwGetProcAddress(const char* name) {
2224
return emscripten_GetProcAddress(name);
2325
}
26+
27+
#endif

system/lib/gl/webgl1.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,8 @@ RET_SYNC_GL_FUNCTION_3(EM_FUNC_SIG_VIII, void, glGetQueryObjectui64vEXT, GLenum,
579579

580580
#endif // ~(__EMSCRIPTEN_PTHREADS__ && __EMSCRIPTEN_OFFSCREEN_FRAMEBUFFER__)
581581

582+
#if GL_ENABLE_GET_PROC_ADDRESS
583+
582584
// Returns a function pointer to the given WebGL 1 extension function, when queried without
583585
// a GL extension suffix such as "EXT", "OES", or "ANGLE". This function is used by
584586
// emscripten_GetProcAddress() to implement legacy GL emulation semantics for portability.
@@ -797,3 +799,5 @@ void *emscripten_webgl1_get_proc_address(const char *name) {
797799

798800
return 0;
799801
}
802+
803+
#endif

0 commit comments

Comments
 (0)