Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GL_ENABLE_GET_PROC_ADDRESS #20802

Merged
merged 1 commit into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ See docs/process.md for more on how version tagging works.
- Update GLFW handling of touch events to avoid sending duplicate mousedown and
and mouseup events. Maps touchmove to mousemove events for a single primary
touch. (#20805)
- Breaking change: Using the `*glGetProcAddress()` family of functions now
requires passing a linker flag -sGL_ENABLE_GET_PROC_ADDRESS. This prevents
ports of native GL renderers from later accidentally attempting to activate
"dormant" features if web browser implementations gain new WebGL extensions in
the future, which `*glGetProcAddress()` is not able to support. (#20802)

3.1.49 - 11/14/23
-----------------
Expand Down
1 change: 1 addition & 0 deletions embuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
'libmimalloc',
'libmimalloc-mt',
'libGL',
'libGL-getprocaddr',
'libhtml5',
'libsockets',
'libstubs',
Expand Down
5 changes: 5 additions & 0 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,11 @@ def phase_setup(options, state, newargs):
else:
settings.SUPPORT_LONGJMP = 'emscripten'

# SDL2 requires eglGetProcAddress() to work.
# NOTE: if SDL2 is updated to not rely on eglGetProcAddress(), this can be removed
if settings.USE_SDL == 2 or settings.USE_SDL_MIXER == 2 or settings.USE_SDL_GFX == 2:
juj marked this conversation as resolved.
Show resolved Hide resolved
default_setting('GL_ENABLE_GET_PROC_ADDRESS', 1)

return (newargs, input_files)


Expand Down
2 changes: 1 addition & 1 deletion src/library_exceptions_stub.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var LibraryExceptions = {};
].forEach(function(name) {
LibraryExceptions[name] = function() { abort(); };
#if !INCLUDE_FULL_LIBRARY
// This method of link-time error genertation is not compatible with INCLUDE_FULL_LIBRARY
// This method of link-time error generation is not compatible with INCLUDE_FULL_LIBRARY
LibraryExceptions[name + '__deps'] = [function() {
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.`);
}];
Expand Down
6 changes: 6 additions & 0 deletions src/library_sigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ sigs = {
SDL_GL_DeleteContext__sig: 'vp',
SDL_GL_ExtensionSupported__sig: 'ip',
SDL_GL_GetAttribute__sig: 'iip',
SDL_GL_GetProcAddress__sig: 'pp',
SDL_GL_GetSwapInterval__sig: 'i',
SDL_GL_MakeCurrent__sig: 'ipp',
SDL_GL_SetAttribute__sig: 'iii',
Expand Down Expand Up @@ -547,6 +548,7 @@ sigs = {
eglGetCurrentSurface__sig: 'pi',
eglGetDisplay__sig: 'pp',
eglGetError__sig: 'i',
eglGetProcAddress__sig: 'pp',
eglInitialize__sig: 'ippp',
eglMakeCurrent__sig: 'ipppp',
eglQueryAPI__sig: 'i',
Expand Down Expand Up @@ -849,6 +851,8 @@ sigs = {
emscripten_wasm_worker_post_function_vii__sig: 'vipii',
emscripten_wasm_worker_post_function_viii__sig: 'vipiii',
emscripten_wasm_worker_self_id__sig: 'i',
emscripten_webgl1_get_proc_address__sig: 'pp',
emscripten_webgl2_get_proc_address__sig: 'pp',
emscripten_webgl_commit_frame__sig: 'i',
emscripten_webgl_create_context__sig: 'ppp',
emscripten_webgl_destroy_context__sig: 'ip',
Expand All @@ -870,6 +874,7 @@ sigs = {
emscripten_webgl_get_parameter_o__sig: 'ii',
emscripten_webgl_get_parameter_utf8__sig: 'pi',
emscripten_webgl_get_parameter_v__sig: 'iipii',
emscripten_webgl_get_proc_address__sig: 'pp',
emscripten_webgl_get_program_info_log_utf8__sig: 'pi',
emscripten_webgl_get_program_parameter_d__sig: 'dii',
emscripten_webgl_get_shader_info_log_utf8__sig: 'pi',
Expand Down Expand Up @@ -1387,6 +1392,7 @@ sigs = {
glfwGetMouseWheel__sig: 'i',
glfwGetNumberOfProcessors__sig: 'i',
glfwGetPrimaryMonitor__sig: 'p',
glfwGetProcAddress__sig: 'pp',
glfwGetRequiredInstanceExtensions__sig: 'pp',
glfwGetThreadID__sig: 'i',
glfwGetTime__sig: 'd',
Expand Down
73 changes: 73 additions & 0 deletions src/library_webgl.js
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,58 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}};
disableHalfFloatExtensionIfBroken(ctx);
#endif

// If end user enables *glGetProcAddress() functionality, 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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about if the user calls glGetString(GL_EXTENSIONS) but they don't set GL_ENABLE_GET_PROC_ADDRESS? Is it OK that they see the full unfiltered list in this case?

Similarly emscripten_webgl_get_supported_extensions.. if GL_ENABLE_GET_PROC_ADDRESS is not set what do we expect it to return?

How about GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS which is enabled by default.. do we want to see the full unfiltered list by default?

How about the existing wrapping of getSupportedExtensions by GL_DISABLE_HALF_FLOAT_EXTENSION_IF_BROKEN? Does that wrapper simply layer in top of this one?

Copy link
Collaborator

@kainino0x kainino0x Dec 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be OK to expose the unfiltered list in all cases when GetProcAddress is not enabled, because any code that uses an entry point Emscripten doesn't implement will cause a linker error. (And any extension that doesn't have entry points is OK.) It is a little unfortunate that they will have to #ifdef __EMSCRIPTEN__ though instead of #ifdef GL_EXT_clip_control which many codebases will already have.

Come to think of it, it must be spec-valid in OpenGL for an implementation to list extensions that aren't available in the header - because you can use an older header with a newer driver. It's less guaranteed that applications would be robust to this though.

How about the existing wrapping of getSupportedExtensions by GL_DISABLE_HALF_FLOAT_EXTENSION_IF_BROKEN? Does that wrapper simply layer in top of this one?

That wrapper shadows WebGLRenderingContext.prototype.getSupportedExtensions with ctx.getSupportedExtensions so I think it will apply first (at the JS level) and then this patch will apply on top.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's less guaranteed that applications would be robust to this though.

Er, my point is, Emscripten could remove them from the header instead of filtering them out, and that would be a less robust but technically valid fix (that would work for Filament at least in this case).

Actually it would be more robust than I thought - if we did this, we'd be disabling not just the static entrypoint glClipControlEXT, but also PFNGLCLIPCONTROLEXTPROC which should be used by any program that's using GetProcAddress on that function. Example: https://github.com/google/filament/blob/b007e9137eb029e256675eceb5fd52e6b873cecd/filament/backend/src/opengl/gl_headers.h#L132

Copy link
Collaborator Author

@juj juj Dec 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about if the user calls glGetString(GL_EXTENSIONS) but they don't set GL_ENABLE_GET_PROC_ADDRESS? Is it OK that they see the full unfiltered list in this case?

Yes that is ok. That is just the common case as if user had hand-written native JavaScript code and called ctx.getSupportedExtensions() in it.

Similarly emscripten_webgl_get_supported_extensions.. if GL_ENABLE_GET_PROC_ADDRESS is not set what do we expect it to return?

Same as above. All extensions that the WebGL implementation advertises, unfiltered.

How about GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS which is enabled by default.. do we want to see the full unfiltered list by default?

Yes. The root problem is in the use of the glGetProcAddress() function, because it is unable to truly enumerate extensions.

How about the existing wrapping of getSupportedExtensions by GL_DISABLE_HALF_FLOAT_EXTENSION_IF_BROKEN? Does that wrapper simply layer in top of this one?

Yeah, the two things should cascade well together.

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 @@ -4219,6 +4271,27 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}};
#endif
};

#if !GL_ENABLE_GET_PROC_ADDRESS
[
'emscripten_webgl1_get_proc_address',
'emscripten_webgl2_get_proc_address',
'emscripten_webgl_get_proc_address',
'SDL_GL_GetProcAddress',
'eglGetProcAddress',
'glfwGetProcAddress'
].forEach(function(name) {
LibraryGL[name] = function(name) { abort(); return 0; };
// Due to the two pass nature of compiling .js files,
// in INCLUDE_FULL_LIBRARY mode, we must include the above
// stub functions, but not their __deps message handlers.
#if !INCLUDE_FULL_LIBRARY
LibraryGL[name + '__deps'] = [function() {
error(`linker: Undefined symbol: ${name}(). Please pass -sGL_ENABLE_GET_PROC_ADDRESS at link time to link in ${name}().`);
}];
#endif
});
#endif

// Simple pass-through functions.
// - Starred ones have return values.
// - [X] ones have X in the C name but not in the JS name
Expand Down
7 changes: 7 additions & 0 deletions src/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,13 @@ var GL_DISABLE_HALF_FLOAT_EXTENSION_IF_BROKEN = false;
// Set this to 0 to force-disable the workaround if you know the issue will not affect you.
var GL_WORKAROUND_SAFARI_GETCONTEXT_BUG = true;

// If 1, link with support to *glGetProcAddress() functionality.
// In WebGL, *glGetProcAddress() causes a substantial code size and performance impact, since WebGL
// does not natively provide such functionality, and it must be emulated. Using *glGetProcAddress()
// is not recommended. If you still need to use this, e.g. when porting an existing renderer,
// you can link with -sGL_ENABLE_GET_PROC_ADDRESS=1 to get support for this functionality.
var GL_ENABLE_GET_PROC_ADDRESS = false;

// Use JavaScript math functions like Math.tan. This saves code size as we can avoid shipping
// compiled musl code. However, it can be significantly slower as it calls out to JS. It
// also may give different results as JS math is specced somewhat differently than libc, and
Expand Down
4 changes: 4 additions & 0 deletions system/lib/gl/gl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,8 @@ GLAPI void APIENTRY emscripten_glGetObjectParameteriv (GLhandleARB obj, GLenum p
GLAPI void APIENTRY emscripten_glGetInfoLog (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog);
GLAPI void APIENTRY emscripten_glBindProgram (GLenum target, GLuint program);

#if GL_ENABLE_GET_PROC_ADDRESS

extern void *emscripten_webgl1_get_proc_address(const char *name);
extern void *_webgl1_match_ext_proc_address_without_suffix(const char *name);
extern void *emscripten_webgl2_get_proc_address(const char *name);
Expand Down Expand Up @@ -1837,3 +1839,5 @@ extern void *emscripten_webgl_get_proc_address(const char *name)
#endif
return ptr;
}

#endif
4 changes: 4 additions & 0 deletions system/lib/gl/libprocaddr.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

// GL proc address library integration

#if GL_ENABLE_GET_PROC_ADDRESS

extern void* emscripten_GetProcAddress(const char *name);

__attribute__((weak)) // SDL2 will link in its own version of this
Expand All @@ -21,3 +23,5 @@ void* eglGetProcAddress(const char* name) {
void* glfwGetProcAddress(const char* name) {
return emscripten_GetProcAddress(name);
}

#endif
4 changes: 4 additions & 0 deletions system/lib/gl/webgl1.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,8 @@ RET_SYNC_GL_FUNCTION_3(EM_FUNC_SIG_VIII, void, glGetQueryObjectui64vEXT, GLenum,

#endif // ~(__EMSCRIPTEN_PTHREADS__ && __EMSCRIPTEN_OFFSCREEN_FRAMEBUFFER__)

#if GL_ENABLE_GET_PROC_ADDRESS

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

return 0;
}

#endif
8 changes: 8 additions & 0 deletions system/lib/gl/webgl2.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* University of Illinois/NCSA Open Source License. Both these licenses can be
* found in the LICENSE file.
*/
#if defined(__EMSCRIPTEN_FULL_ES3__) || MAX_WEBGL_VERSION >= 2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this outer #if required?


#include <emscripten/threading.h>
#include <emscripten.h>
#include <string.h>
Expand Down Expand Up @@ -162,6 +164,8 @@ GL_APICALL void GL_APIENTRY glDrawBuffersWEBGL(GLsizei n, const GLenum *bufs) {

#endif // ~__EMSCRIPTEN_PTHREADS__) && __EMSCRIPTEN_OFFSCREEN_FRAMEBUFFER__

#if GL_ENABLE_GET_PROC_ADDRESS

// Returns a function pointer to the given WebGL 2 extension function, when queried without
// a GL extension suffix such as "EXT", "OES", or "ANGLE". This function is used by
// emscripten_GetProcAddress() to implement legacy GL emulation semantics for portability.
Expand Down Expand Up @@ -319,3 +323,7 @@ void *emscripten_webgl2_get_proc_address(const char *name) {

return 0;
}

#endif // GL_ENABLE_GET_PROC_ADDRESS

#endif // defined(__EMSCRIPTEN_FULL_ES3__) || MAX_WEBGL_VERSION >= 2
26 changes: 13 additions & 13 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1329,7 +1329,7 @@ def test_webgl_context_attributes(self):
self.btest_exit('test_webgl_context_attributes_glut.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lglut', '-lGLEW'])
self.btest_exit('test_webgl_context_attributes_sdl.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lSDL', '-lGLEW'])
if not self.is_wasm64():
self.btest_exit('test_webgl_context_attributes_sdl2.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-sUSE_SDL=2', '-lGLEW'])
self.btest_exit('test_webgl_context_attributes_sdl2.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-sUSE_SDL=2', '-lGLEW', '-sGL_ENABLE_GET_PROC_ADDRESS=1'])
self.btest_exit('test_webgl_context_attributes_glfw.c', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED', '-DALPHA_ACTIVATED', '-lGL', '-lglfw', '-lGLEW'])

# perform tests with attributes desactivated
Expand Down Expand Up @@ -1584,7 +1584,7 @@ def test_sdl_ogl_p(self):
def test_sdl_ogl_proc_alias(self):
shutil.copyfile(test_file('screenshot.png'), 'screenshot.png')
self.btest('test_sdl_ogl_proc_alias.c', reference='screenshot-gray-purple.png', reference_slack=1,
args=['-O2', '-g2', '-sINLINING_LIMIT', '--preload-file', 'screenshot.png', '-sLEGACY_GL_EMULATION', '--use-preload-plugins', '-lSDL', '-lGL'])
args=['-O2', '-g2', '-sINLINING_LIMIT', '--preload-file', 'screenshot.png', '-sLEGACY_GL_EMULATION', '-sGL_ENABLE_GET_PROC_ADDRESS', '--use-preload-plugins', '-lSDL', '-lGL'])

@requires_graphics_hardware
def test_sdl_fog_simple(self):
Expand Down Expand Up @@ -1619,11 +1619,11 @@ def test_sdl_fog_linear(self):
@requires_graphics_hardware
def test_glfw(self):
# Using only the `-l` flag
self.btest_exit('test_glfw.c', args=['-sLEGACY_GL_EMULATION', '-lglfw', '-lGL'])
self.btest_exit('test_glfw.c', args=['-sLEGACY_GL_EMULATION', '-lglfw', '-lGL', '-sGL_ENABLE_GET_PROC_ADDRESS'])
# Using only the `-s` flag
self.btest_exit('test_glfw.c', args=['-sLEGACY_GL_EMULATION', '-sUSE_GLFW=2', '-lGL'])
self.btest_exit('test_glfw.c', args=['-sLEGACY_GL_EMULATION', '-sUSE_GLFW=2', '-lGL', '-sGL_ENABLE_GET_PROC_ADDRESS'])
# Using both `-s` and `-l` flags
self.btest_exit('test_glfw.c', args=['-sLEGACY_GL_EMULATION', '-sUSE_GLFW=2', '-lglfw', '-lGL'])
self.btest_exit('test_glfw.c', args=['-sLEGACY_GL_EMULATION', '-sUSE_GLFW=2', '-lglfw', '-lGL', '-sGL_ENABLE_GET_PROC_ADDRESS'])

def test_glfw_minimal(self):
self.btest_exit('test_glfw_minimal.c', args=['-lglfw', '-lGL'])
Expand All @@ -1633,7 +1633,7 @@ def test_glfw_time(self):
self.btest_exit('test_glfw_time.c', args=['-sUSE_GLFW=3', '-lglfw', '-lGL'])

def _test_egl_base(self, *args):
self.btest_exit('test_egl.c', args=['-O2', '-lEGL', '-lGL'] + list(args))
self.btest_exit('test_egl.c', args=['-O2', '-lEGL', '-lGL', '-sGL_ENABLE_GET_PROC_ADDRESS'] + list(args))

@requires_graphics_hardware
def test_egl(self):
Expand Down Expand Up @@ -1815,7 +1815,7 @@ def test_glgears_animation(self):

@requires_graphics_hardware
def test_fulles2_sdlproc(self):
self.btest_exit('full_es2_sdlproc.c', assert_returncode=1, args=['-sGL_TESTING', '-DHAVE_BUILTIN_SINCOS', '-sFULL_ES2', '-lGL', '-lSDL', '-lglut'])
self.btest_exit('full_es2_sdlproc.c', assert_returncode=1, args=['-sGL_TESTING', '-DHAVE_BUILTIN_SINCOS', '-sFULL_ES2', '-lGL', '-lSDL', '-lglut', '-sGL_ENABLE_GET_PROC_ADDRESS'])

@requires_graphics_hardware
def test_glgears_deriv(self):
Expand Down Expand Up @@ -1998,12 +1998,12 @@ def test_glframebufferattachmentinfo(self):
@no_wasm64('TODO: LEGACY_GL_EMULATION + wasm64')
@requires_graphics_hardware
def test_sdl_glshader(self):
self.btest('test_sdl_glshader.c', reference='browser/test_sdl_glshader.png', args=['-O2', '--closure=1', '-sLEGACY_GL_EMULATION', '-lGL', '-lSDL'])
self.btest('test_sdl_glshader.c', reference='browser/test_sdl_glshader.png', args=['-O2', '--closure=1', '-sLEGACY_GL_EMULATION', '-lGL', '-lSDL', '-sGL_ENABLE_GET_PROC_ADDRESS'])

@no_wasm64('TODO: LEGACY_GL_EMULATION + wasm64')
@requires_graphics_hardware
def test_sdl_glshader2(self):
self.btest_exit('test_sdl_glshader2.c', args=['-sLEGACY_GL_EMULATION', '-lGL', '-lSDL'], also_proxied=True)
self.btest_exit('test_sdl_glshader2.c', args=['-sLEGACY_GL_EMULATION', '-lGL', '-lSDL', '-sGL_ENABLE_GET_PROC_ADDRESS'], also_proxied=True)

@requires_graphics_hardware
def test_gl_glteximage(self):
Expand Down Expand Up @@ -2145,7 +2145,7 @@ def test_cubegeom_proc(self, opts):
return glBindBuffer;
}
''')
self.btest('third_party/cubegeom/cubegeom_proc.c', reference='third_party/cubegeom/cubegeom.png', args=opts + ['side.c', '-sLEGACY_GL_EMULATION', '-lGL', '-lSDL'])
self.btest('third_party/cubegeom/cubegeom_proc.c', reference='third_party/cubegeom/cubegeom.png', args=opts + ['side.c', '-sLEGACY_GL_EMULATION', '-lGL', '-lSDL', '-sGL_ENABLE_GET_PROC_ADDRESS'])

@no_wasm64('wasm64 + LEGACY_GL_EMULATION')
@also_with_wasmfs
Expand Down Expand Up @@ -2225,12 +2225,12 @@ def test_cubegeom_pre_vao_regal(self):
@requires_graphics_hardware
@no_swiftshader
def test_cubegeom_pre2_vao(self):
self.btest('third_party/cubegeom/cubegeom_pre2_vao.c', reference='third_party/cubegeom/cubegeom_pre_vao.png', args=['-sLEGACY_GL_EMULATION', '-lGL', '-lSDL'])
self.btest('third_party/cubegeom/cubegeom_pre2_vao.c', reference='third_party/cubegeom/cubegeom_pre_vao.png', args=['-sLEGACY_GL_EMULATION', '-lGL', '-lSDL', '-sGL_ENABLE_GET_PROC_ADDRESS'])

@no_wasm64('wasm64 + LEGACY_GL_EMULATION')
@requires_graphics_hardware
def test_cubegeom_pre2_vao2(self):
self.btest('third_party/cubegeom/cubegeom_pre2_vao2.c', reference='third_party/cubegeom/cubegeom_pre2_vao2.png', args=['-sLEGACY_GL_EMULATION', '-lGL', '-lSDL'])
self.btest('third_party/cubegeom/cubegeom_pre2_vao2.c', reference='third_party/cubegeom/cubegeom_pre2_vao2.png', args=['-sLEGACY_GL_EMULATION', '-lGL', '-lSDL', '-sGL_ENABLE_GET_PROC_ADDRESS'])

@no_wasm64('wasm64 + LEGACY_GL_EMULATION')
@requires_graphics_hardware
Expand Down Expand Up @@ -3002,7 +3002,7 @@ def in_html(expected):
@requires_graphics_hardware
@parameterized({
'no_gl': (['-DCLIENT_API=GLFW_NO_API'],),
'gl_es': (['-DCLIENT_API=GLFW_OPENGL_ES_API'],)
'gl_es': (['-DCLIENT_API=GLFW_OPENGL_ES_API', '-sGL_ENABLE_GET_PROC_ADDRESS'],)
})
def test_glfw3(self, args):
for opts in [[], ['-sLEGACY_GL_EMULATION'], ['-Os', '--closure=1']]:
Expand Down
1 change: 1 addition & 0 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -9870,6 +9870,7 @@ def test_abort_on_exceptions_pthreads(self):
@needs_dylink
def test_gl_main_module(self):
self.set_setting('MAIN_MODULE')
self.emcc_args += ['-sGL_ENABLE_GET_PROC_ADDRESS']
self.do_runf('core/test_gl_get_proc_address.c')

@needs_dylink
Expand Down
15 changes: 11 additions & 4 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -2416,7 +2416,7 @@ def test_undefined_symbols(self, action):
delete_file('a.out.js')
print('checking "%s" %s' % (args, value))
extra = ['-s', action + '_ON_UNDEFINED_SYMBOLS=%d' % value] if action else []
proc = self.run_process([EMCC, '-sUSE_SDL', 'main.c'] + extra + args, stderr=PIPE, check=False)
proc = self.run_process([EMCC, '-sUSE_SDL', '-sGL_ENABLE_GET_PROC_ADDRESS', 'main.c'] + extra + args, stderr=PIPE, check=False)
if common.EMTEST_VERBOSE:
print(proc.stderr)
if value or action is None:
Expand Down Expand Up @@ -2460,9 +2460,16 @@ def test_undefined_data_symbols(self):

def test_GetProcAddress_LEGACY_GL_EMULATION(self):
# without legacy gl emulation, getting a proc from there should fail
self.do_other_test('test_GetProcAddress_LEGACY_GL_EMULATION.cpp', args=['0'], emcc_args=['-sLEGACY_GL_EMULATION=0'])
self.do_other_test('test_GetProcAddress_LEGACY_GL_EMULATION.cpp', args=['0'], emcc_args=['-sLEGACY_GL_EMULATION=0', '-sGL_ENABLE_GET_PROC_ADDRESS'])
# with it, it should work
self.do_other_test('test_GetProcAddress_LEGACY_GL_EMULATION.cpp', args=['1'], emcc_args=['-sLEGACY_GL_EMULATION'])
self.do_other_test('test_GetProcAddress_LEGACY_GL_EMULATION.cpp', args=['1'], emcc_args=['-sLEGACY_GL_EMULATION', '-sGL_ENABLE_GET_PROC_ADDRESS'])

# Verifies that is user is building without -sGL_ENABLE_GET_PROC_ADDRESS, then
# at link time they should get a helpful error message guiding them to enable
# the option.
def test_get_proc_address_error_message(self):
err = self.expect_fail([EMCC, test_file('other/test_GetProcAddress_LEGACY_GL_EMULATION.cpp')])
self.assertContained('error: linker: Undefined symbol: SDL_GL_GetProcAddress(). Please pass -sGL_ENABLE_GET_PROC_ADDRESS at link time to link in SDL_GL_GetProcAddress().', err)

def test_prepost(self):
create_file('main.c', '''
Expand Down Expand Up @@ -12608,7 +12615,7 @@ def test_explicit_gl_linking(self):
# Test that libGL can be linked explicitly via `-lGL` rather than implicitly.
# Here we use NO_AUTO_NATIVE_LIBRARIES to disable the implicitly linking that normally
# includes the native GL library.
self.run_process([EMCC, test_file('other/test_explicit_gl_linking.c'), '-sNO_AUTO_NATIVE_LIBRARIES', '-lGL'])
self.run_process([EMCC, test_file('other/test_explicit_gl_linking.c'), '-sNO_AUTO_NATIVE_LIBRARIES', '-lGL', '-sGL_ENABLE_GET_PROC_ADDRESS'])

def test_no_main_with_PROXY_TO_PTHREAD(self):
create_file('lib.c', r'''
Expand Down
Loading