Skip to content

Commit c6cabd5

Browse files
authored
Fix LEGACY_GL_EMULATION + MAIN_MODULE (#22456)
Fixes: #22431
1 parent f104079 commit c6cabd5

File tree

4 files changed

+83
-42
lines changed

4 files changed

+83
-42
lines changed

embuilder.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
'libmimalloc-mt',
6767
'libGL',
6868
'libGL-getprocaddr',
69+
'libGL-emu-getprocaddr',
6970
'libGL-emu-webgl2-ofb-getprocaddr',
7071
'libGL-webgl2-ofb-getprocaddr',
7172
'libGL-ww-getprocaddr',

src/library_glemu.js

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
*/
66

77
{{{
8+
globalThis.copySigs = (func) => {
9+
if (!RELOCATABLE) return '';
10+
return ` _${func}.sig = _emscripten_${func}.sig = orig_${func}.sig;`;
11+
};
812
globalThis.fromPtr = (arg) => {
913
if (CAN_ADDRESS_2GB) {
1014
return `${arg} >>>= 0`;
1115
} else if (MEMORY64) {
1216
return `${arg} = Number(${arg})`;
1317
}
1418
return '';
15-
}
19+
};
1620
null;
1721
}}}
1822

@@ -199,7 +203,7 @@ var LibraryGLEmulation = {
199203
0x80A0: 1 // GL_SAMPLE_COVERAGE
200204
};
201205

202-
var glEnable = _glEnable;
206+
var orig_glEnable = _glEnable;
203207
_glEnable = _emscripten_glEnable = (cap) => {
204208
// Clean up the renderer on any change to the rendering state. The optimization of
205209
// skipping renderer setup is aimed at the case of multiple glDraw* right after each other
@@ -247,10 +251,11 @@ var LibraryGLEmulation = {
247251
} else if (!(cap in validCapabilities)) {
248252
return;
249253
}
250-
glEnable(cap);
254+
orig_glEnable(cap);
251255
};
256+
{{{ copySigs('glEnable') }}}
252257

253-
var glDisable = _glDisable;
258+
var orig_glDisable = _glDisable;
254259
_glDisable = _emscripten_glDisable = (cap) => {
255260
GLImmediate.lastRenderer?.cleanup();
256261
if (cap == 0xB60 /* GL_FOG */) {
@@ -296,9 +301,11 @@ var LibraryGLEmulation = {
296301
} else if (!(cap in validCapabilities)) {
297302
return;
298303
}
299-
glDisable(cap);
304+
orig_glDisable(cap);
300305
};
306+
{{{ copySigs('glDisable') }}}
301307

308+
var orig_glIsEnabled = _glIsEnabled;
302309
_glIsEnabled = _emscripten_glIsEnabled = (cap) => {
303310
if (cap == 0xB60 /* GL_FOG */) {
304311
return GLEmulation.fogEnabled ? 1 : 0;
@@ -317,8 +324,9 @@ var LibraryGLEmulation = {
317324
}
318325
return GLctx.isEnabled(cap);
319326
};
327+
{{{ copySigs('glIsEnabled') }}}
320328

321-
var glGetBooleanv = _glGetBooleanv;
329+
var orig_glGetBooleanv = _glGetBooleanv;
322330
_glGetBooleanv = _emscripten_glGetBooleanv = (pname, p) => {
323331
var attrib = GLEmulation.getAttributeFromCapability(pname);
324332
if (attrib !== null) {
@@ -327,10 +335,11 @@ var LibraryGLEmulation = {
327335
{{{ makeSetValue('p', '0', 'result === true ? 1 : 0', 'i8') }}};
328336
return;
329337
}
330-
glGetBooleanv(pname, p);
338+
orig_glGetBooleanv(pname, p);
331339
};
340+
{{{ copySigs('glGetBooleanv') }}}
332341

333-
var glGetIntegerv = _glGetIntegerv;
342+
var orig_glGetIntegerv = _glGetIntegerv;
334343
_glGetIntegerv = _emscripten_glGetIntegerv = (pname, params) => {
335344
{{{ fromPtr('params') }}}
336345
switch (pname) {
@@ -409,10 +418,11 @@ var LibraryGLEmulation = {
409418
return;
410419
}
411420
}
412-
glGetIntegerv(pname, params);
421+
orig_glGetIntegerv(pname, params);
413422
};
423+
{{{ copySigs('glGetIntegerv') }}}
414424

415-
var glGetString = _glGetString;
425+
var orig_glGetString = _glGetString;
416426
_glGetString = _emscripten_glGetString = (name_) => {
417427
if (GL.stringCache[name_]) return GL.stringCache[name_];
418428
switch (name_) {
@@ -424,8 +434,9 @@ var LibraryGLEmulation = {
424434
);
425435
return GL.stringCache[name_] = {{{ to64('ret') }}};
426436
}
427-
return glGetString(name_);
437+
return orig_glGetString(name_);
428438
};
439+
{{{ copySigs('glGetString') }}}
429440

430441
// Do some automatic rewriting to work around GLSL differences. Note that this must be done in
431442
// tandem with the rest of the program, by itself it cannot suffice.
@@ -435,15 +446,16 @@ var LibraryGLEmulation = {
435446
GL.shaderSources = {};
436447
GL.shaderOriginalSources = {};
437448
#endif
438-
var glCreateShader = _glCreateShader;
449+
var orig_glCreateShader = _glCreateShader;
439450
_glCreateShader = _emscripten_glCreateShader = (shaderType) => {
440-
var id = glCreateShader(shaderType);
451+
var id = orig_glCreateShader(shaderType);
441452
GL.shaderInfos[id] = {
442453
type: shaderType,
443454
ftransform: false
444455
};
445456
return id;
446457
};
458+
{{{ copySigs('glCreateShader') }}}
447459

448460
function ensurePrecision(source) {
449461
if (!/precision +(low|medium|high)p +float *;/.test(source)) {
@@ -452,7 +464,7 @@ var LibraryGLEmulation = {
452464
return source;
453465
}
454466

455-
var glShaderSource = _glShaderSource;
467+
var orig_glShaderSource = _glShaderSource;
456468
_glShaderSource = _emscripten_glShaderSource = (shader, count, string, length) => {
457469
{{{ fromPtr('string') }}}
458470
{{{ fromPtr('length') }}}
@@ -566,8 +578,9 @@ var LibraryGLEmulation = {
566578
#endif
567579
GLctx.shaderSource(GL.shaders[shader], source);
568580
};
581+
{{{ copySigs('glShaderSource') }}}
569582

570-
var glCompileShader = _glCompileShader;
583+
var orig_glCompileShader = _glCompileShader;
571584
_glCompileShader = _emscripten_glCompileShader = (shader) => {
572585
GLctx.compileShader(GL.shaders[shader]);
573586
#if GL_DEBUG
@@ -580,16 +593,18 @@ var LibraryGLEmulation = {
580593
}
581594
#endif
582595
};
596+
{{{ copySigs('glCompileShader') }}}
583597

584598
GL.programShaders = {};
585-
var glAttachShader = _glAttachShader;
599+
var orig_glAttachShader = _glAttachShader;
586600
_glAttachShader = _emscripten_glAttachShader = (program, shader) => {
587601
GL.programShaders[program] ||= [];
588602
GL.programShaders[program].push(shader);
589-
glAttachShader(program, shader);
603+
orig_glAttachShader(program, shader);
590604
};
605+
{{{ copySigs('glAttachShader') }}}
591606

592-
var glDetachShader = _glDetachShader;
607+
var orig_glDetachShader = _glDetachShader;
593608
_glDetachShader = _emscripten_glDetachShader = (program, shader) => {
594609
var programShader = GL.programShaders[program];
595610
if (!programShader) {
@@ -598,10 +613,11 @@ var LibraryGLEmulation = {
598613
}
599614
var index = programShader.indexOf(shader);
600615
programShader.splice(index, 1);
601-
glDetachShader(program, shader);
616+
orig_glDetachShader(program, shader);
602617
};
618+
{{{ copySigs('glDetachShader') }}}
603619

604-
var glUseProgram = _glUseProgram;
620+
var orig_glUseProgram = _glUseProgram;
605621
_glUseProgram = _emscripten_glUseProgram = (program) => {
606622
#if GL_DEBUG
607623
if (GL.debug) {
@@ -618,38 +634,42 @@ var LibraryGLEmulation = {
618634
GLImmediate.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that.
619635
GL.currProgram = program;
620636
GLImmediate.fixedFunctionProgram = 0;
621-
glUseProgram(program);
637+
orig_glUseProgram(program);
622638
}
623639
}
640+
{{{ copySigs('glUseProgram') }}}
624641

625-
var glDeleteProgram = _glDeleteProgram;
642+
var orig_glDeleteProgram = _glDeleteProgram;
626643
_glDeleteProgram = _emscripten_glDeleteProgram = (program) => {
627-
glDeleteProgram(program);
644+
orig_glDeleteProgram(program);
628645
if (program == GL.currProgram) {
629646
GLImmediate.currentRenderer = null; // This changes the FFP emulation shader program, need to recompute that.
630647
GL.currProgram = 0;
631648
}
632649
};
650+
{{{ copySigs('glDeleteProgram') }}}
633651

634652
// If attribute 0 was not bound, bind it to 0 for WebGL performance reasons. Track if 0 is free for that.
635653
var zeroUsedPrograms = {};
636-
var glBindAttribLocation = _glBindAttribLocation;
654+
var orig_glBindAttribLocation = _glBindAttribLocation;
637655
_glBindAttribLocation = _emscripten_glBindAttribLocation = (program, index, name) => {
638656
if (index == 0) zeroUsedPrograms[program] = true;
639-
glBindAttribLocation(program, index, name);
657+
orig_glBindAttribLocation(program, index, name);
640658
};
659+
{{{ copySigs('glBindAttribLocation') }}}
641660

642-
var glLinkProgram = _glLinkProgram;
661+
var orig_glLinkProgram = _glLinkProgram;
643662
_glLinkProgram = _emscripten_glLinkProgram = (program) => {
644663
if (!(program in zeroUsedPrograms)) {
645664
GLctx.bindAttribLocation(GL.programs[program], 0, 'a_position');
646665
}
647-
glLinkProgram(program);
666+
orig_glLinkProgram(program);
648667
};
668+
{{{ copySigs('glLinkProgram') }}}
649669

650-
var glBindBuffer = _glBindBuffer;
670+
var orig_glBindBuffer = _glBindBuffer;
651671
_glBindBuffer = _emscripten_glBindBuffer = (target, buffer) => {
652-
glBindBuffer(target, buffer);
672+
orig_glBindBuffer(target, buffer);
653673
if (target == GLctx.ARRAY_BUFFER) {
654674
if (GLEmulation.currentVao) {
655675
#if ASSERTIONS
@@ -661,8 +681,9 @@ var LibraryGLEmulation = {
661681
if (GLEmulation.currentVao) GLEmulation.currentVao.elementArrayBuffer = buffer;
662682
}
663683
};
684+
{{{ copySigs('glBindBuffer') }}}
664685

665-
var glGetFloatv = _glGetFloatv;
686+
var orig_glGetFloatv = _glGetFloatv;
666687
_glGetFloatv = _emscripten_glGetFloatv = (pname, params) => {
667688
{{{ fromPtr('params') }}}
668689
if (pname == 0xBA6) { // GL_MODELVIEW_MATRIX
@@ -689,39 +710,44 @@ var LibraryGLEmulation = {
689710
} else if (pname == 0xBC2) { // GL_ALPHA_TEST_REF
690711
{{{ makeSetValue('params', '0', 'GLEmulation.alphaTestRef', 'float') }}};
691712
} else {
692-
glGetFloatv(pname, params);
713+
orig_glGetFloatv(pname, params);
693714
}
694715
};
716+
{{{ copySigs('glGetFloatv') }}}
695717

696-
var glHint = _glHint;
718+
var orig_glHint = _glHint;
697719
_glHint = _emscripten_glHint = (target, mode) => {
698720
if (target == 0x84EF) { // GL_TEXTURE_COMPRESSION_HINT
699721
return;
700722
}
701-
glHint(target, mode);
723+
orig_glHint(target, mode);
702724
};
725+
{{{ copySigs('glHint') }}}
703726

704-
var glEnableVertexAttribArray = _glEnableVertexAttribArray;
727+
var orig_glEnableVertexAttribArray = _glEnableVertexAttribArray;
705728
_glEnableVertexAttribArray = _emscripten_glEnableVertexAttribArray = (index) => {
706-
glEnableVertexAttribArray(index);
729+
orig_glEnableVertexAttribArray(index);
707730
GLEmulation.enabledVertexAttribArrays[index] = 1;
708731
if (GLEmulation.currentVao) GLEmulation.currentVao.enabledVertexAttribArrays[index] = 1;
709732
};
733+
{{{ copySigs('glEnableVertexAttribArray') }}}
710734

711-
var glDisableVertexAttribArray = _glDisableVertexAttribArray;
735+
var orig_glDisableVertexAttribArray = _glDisableVertexAttribArray;
712736
_glDisableVertexAttribArray = _emscripten_glDisableVertexAttribArray = (index) => {
713-
glDisableVertexAttribArray(index);
737+
orig_glDisableVertexAttribArray(index);
714738
delete GLEmulation.enabledVertexAttribArrays[index];
715739
if (GLEmulation.currentVao) delete GLEmulation.currentVao.enabledVertexAttribArrays[index];
716740
};
741+
{{{ copySigs('glDisableVertexAttribArray') }}}
717742

718-
var glVertexAttribPointer = _glVertexAttribPointer;
743+
var orig_glVertexAttribPointer = _glVertexAttribPointer;
719744
_glVertexAttribPointer = _emscripten_glVertexAttribPointer = (index, size, type, normalized, stride, pointer) => {
720-
glVertexAttribPointer(index, size, type, normalized, stride, pointer);
745+
orig_glVertexAttribPointer(index, size, type, normalized, stride, pointer);
721746
if (GLEmulation.currentVao) { // TODO: avoid object creation here? likely not hot though
722747
GLEmulation.currentVao.vertexAttribPointers[index] = [index, size, type, normalized, stride, pointer];
723748
}
724749
};
750+
{{{ copySigs('glVertexAttribPointer') }}}
725751
},
726752

727753
getAttributeFromCapability(cap) {

test/test_other.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2340,6 +2340,20 @@ def test_dylink_dependencies(self):
23402340
self.run_process(cmd + ['-L.'])
23412341
self.run_js('a.out.js')
23422342

2343+
def test_dylink_LEGACY_GL_EMULATION(self):
2344+
# LEGACY_GL_EMULATION wraps JS library functions. This test ensure that when it does
2345+
# so it preserves the `.sig` attributes needed by dynamic linking.
2346+
create_file('test.c', r'''
2347+
#include <GLES2/gl2.h>
2348+
#include <stdio.h>
2349+
2350+
int main() {
2351+
printf("glUseProgram: %p\n", &glUseProgram);
2352+
printf("done\n");
2353+
return 0;
2354+
}''')
2355+
self.do_runf('test.c', 'done\n', emcc_args=['-sLEGACY_GL_EMULATION', '-sMAIN_MODULE=2'])
2356+
23432357
def test_js_link(self):
23442358
create_file('main.c', '''
23452359
#include <stdio.h>
@@ -2725,15 +2739,15 @@ def test_undefined_data_symbols(self):
27252739

27262740
def test_GetProcAddress_LEGACY_GL_EMULATION(self):
27272741
# without legacy gl emulation, getting a proc from there should fail
2728-
self.do_other_test('test_GetProcAddress_LEGACY_GL_EMULATION.cpp', args=['0'], emcc_args=['-sLEGACY_GL_EMULATION=0', '-sGL_ENABLE_GET_PROC_ADDRESS'])
2742+
self.do_other_test('test_GetProcAddress_LEGACY_GL_EMULATION.c', args=['0'], emcc_args=['-sLEGACY_GL_EMULATION=0', '-sGL_ENABLE_GET_PROC_ADDRESS'])
27292743
# with it, it should work
2730-
self.do_other_test('test_GetProcAddress_LEGACY_GL_EMULATION.cpp', args=['1'], emcc_args=['-sLEGACY_GL_EMULATION', '-sGL_ENABLE_GET_PROC_ADDRESS'])
2744+
self.do_other_test('test_GetProcAddress_LEGACY_GL_EMULATION.c', args=['1'], emcc_args=['-sLEGACY_GL_EMULATION', '-sGL_ENABLE_GET_PROC_ADDRESS'])
27312745

27322746
# Verifies that is user is building without -sGL_ENABLE_GET_PROC_ADDRESS, then
27332747
# at link time they should get a helpful error message guiding them to enable
27342748
# the option.
27352749
def test_get_proc_address_error_message(self):
2736-
err = self.expect_fail([EMCC, '-sGL_ENABLE_GET_PROC_ADDRESS=0', test_file('other/test_GetProcAddress_LEGACY_GL_EMULATION.cpp')])
2750+
err = self.expect_fail([EMCC, '-sGL_ENABLE_GET_PROC_ADDRESS=0', test_file('other/test_GetProcAddress_LEGACY_GL_EMULATION.c')])
27372751
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)
27382752

27392753
def test_prepost(self):

0 commit comments

Comments
 (0)