diff options
-rwxr-xr-x | emcc | 3 | ||||
-rw-r--r-- | src/jsifier.js | 3 | ||||
-rw-r--r-- | src/library.js | 29 | ||||
-rw-r--r-- | src/library_gl.js | 15 | ||||
-rw-r--r-- | src/library_openal.js | 17 | ||||
-rw-r--r-- | src/parseTools.js | 9 | ||||
-rw-r--r-- | tests/gl_vertex_buffer.c | 195 | ||||
-rw-r--r-- | tests/gl_vertex_buffer.png | bin | 0 -> 47668 bytes | |||
-rw-r--r-- | tests/gl_vertex_buffer_pre.c | 177 | ||||
-rw-r--r-- | tests/gl_vertex_buffer_pre.png | bin | 0 -> 83534 bytes | |||
-rw-r--r-- | tests/test_browser.py | 6 | ||||
-rw-r--r-- | tests/test_core.py | 137 | ||||
-rw-r--r-- | tools/shared.py | 26 |
13 files changed, 579 insertions, 38 deletions
@@ -1125,6 +1125,9 @@ try: else: logging.debug('using response file for EXPORTED_FUNCTIONS, make sure it includes _malloc and _free') + if shared.Settings.ASM_JS and shared.Settings.DLOPEN_SUPPORT: + assert shared.Settings.DISABLE_EXCEPTION_CATCHING, 'no exceptions support with dlopen in asm yet' + ## Compile source code to bitcode logging.debug('compiling to bitcode') diff --git a/src/jsifier.js b/src/jsifier.js index 8592364d..f5682a1b 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -338,6 +338,7 @@ function JSify(data, functionsOnly, givenFunctions) { // External variables in shared libraries should not be declared as // they would shadow similarly-named globals in the parent, so do nothing here. if (BUILD_AS_SHARED_LIB) return ret; + if (SIDE_MODULE) return []; // Library items need us to emit something, but everything else requires nothing. if (!LibraryManager.library[item.ident.slice(1)]) return ret; } @@ -1408,7 +1409,7 @@ function JSify(data, functionsOnly, givenFunctions) { var extCall = false; if (ASM_JS && funcData.setjmpTable) forceByPointer = true; // in asm.js mode, we must do an invoke for each call - if (ASM_JS && DLOPEN_SUPPORT && !invoke) extCall = true; // go out, to be able to access other modules TODO: optimize + if (ASM_JS && DLOPEN_SUPPORT && !invoke && !funcData.setjmpTable) extCall = true; // go out, to be able to access other modules TODO: optimize ident = Variables.resolveAliasToIdent(ident); var shortident = ident.slice(1); diff --git a/src/library.js b/src/library.js index 7894e033..272f77b0 100644 --- a/src/library.js +++ b/src/library.js @@ -4273,9 +4273,11 @@ LibraryManager.library = { __cxa_guard_release: function() {}, __cxa_guard_abort: function() {}, +#if USE_TYPED_ARRAYS != 2 _ZTVN10__cxxabiv119__pointer_type_infoE: [0], // is a pointer _ZTVN10__cxxabiv117__class_type_infoE: [1], // no inherited classes _ZTVN10__cxxabiv120__si_class_type_infoE: [2], // yes inherited classes +#endif // Exceptions __cxa_allocate_exception: function(size) { @@ -5296,8 +5298,8 @@ LibraryManager.library = { ['i32', 'tm_zone']]), // Statically allocated time struct. __tm_current: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STATIC)', - // Statically allocated timezone strings. - __tm_timezones: {}, + // Statically allocated timezone string. We only use GMT as a timezone. + __tm_timezone: 'allocate(intArrayFromString("GMT"), "i8", ALLOC_STATIC)', // Statically allocated time strings. __tm_formatted: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STATIC)', @@ -5325,7 +5327,7 @@ LibraryManager.library = { return _gmtime_r(time, ___tm_current); }, - gmtime_r__deps: ['__tm_struct_layout', '__tm_timezones'], + gmtime_r__deps: ['__tm_struct_layout', '__tm_timezone'], gmtime_r: function(time, tmPtr) { var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000); var offsets = ___tm_struct_layout; @@ -5347,12 +5349,7 @@ LibraryManager.library = { start.setUTCMilliseconds(0); var yday = Math.floor((date.getTime() - start.getTime()) / (1000 * 60 * 60 * 24)); {{{ makeSetValue('tmPtr', 'offsets.tm_yday', 'yday', 'i32') }}} - - var timezone = "GMT"; - if (!(timezone in ___tm_timezones)) { - ___tm_timezones[timezone] = allocate(intArrayFromString(timezone), 'i8', ALLOC_NORMAL); - } - {{{ makeSetValue('tmPtr', 'offsets.tm_zone', '___tm_timezones[timezone]', 'i32') }}} + {{{ makeSetValue('tmPtr', 'offsets.tm_zone', '___tm_timezone', 'i32') }}} return tmPtr; }, @@ -5371,7 +5368,7 @@ LibraryManager.library = { return _localtime_r(time, ___tm_current); }, - localtime_r__deps: ['__tm_struct_layout', '__tm_timezones', 'tzset'], + localtime_r__deps: ['__tm_struct_layout', '__tm_timezone', 'tzset'], localtime_r: function(time, tmPtr) { _tzset(); var offsets = ___tm_struct_layout; @@ -5392,11 +5389,7 @@ LibraryManager.library = { var dst = Number(start.getTimezoneOffset() != date.getTimezoneOffset()); {{{ makeSetValue('tmPtr', 'offsets.tm_isdst', 'dst', 'i32') }}} - var timezone = 'GMT'; // XXX do not rely on browser timezone info, it is very unpredictable | date.toString().match(/\(([A-Z]+)\)/)[1]; - if (!(timezone in ___tm_timezones)) { - ___tm_timezones[timezone] = allocate(intArrayFromString(timezone), 'i8', ALLOC_NORMAL); - } - {{{ makeSetValue('tmPtr', 'offsets.tm_zone', '___tm_timezones[timezone]', 'i32') }}} + {{{ makeSetValue('tmPtr', 'offsets.tm_zone', '___tm_timezone', 'i32') }}} return tmPtr; }, @@ -6078,7 +6071,7 @@ LibraryManager.library = { // int clock_gettime(clockid_t clk_id, struct timespec *tp); var now = Date.now(); {{{ makeSetValue('tp', '___timespec_struct_layout.tv_sec', 'Math.floor(now/1000)', 'i32') }}}; // seconds - {{{ makeSetValue('tp', '___timespec_struct_layout.tv_nsec', '0', 'i32') }}}; // nanoseconds - not supported + {{{ makeSetValue('tp', '___timespec_struct_layout.tv_nsec', '(now % 1000) * 1000 * 1000', 'i32') }}}; // nanoseconds (really milliseconds) return 0; }, clock_settime: function(clk_id, tp) { @@ -6090,7 +6083,7 @@ LibraryManager.library = { clock_getres: function(clk_id, res) { // int clock_getres(clockid_t clk_id, struct timespec *res); {{{ makeSetValue('res', '___timespec_struct_layout.tv_sec', '1', 'i32') }}} - {{{ makeSetValue('res', '___timespec_struct_layout.tv_nsec', '0', 'i32') }}} + {{{ makeSetValue('res', '___timespec_struct_layout.tv_nsec', '1000 * 1000', 'i32') }}} // resolution is milliseconds return 0; }, @@ -7399,7 +7392,7 @@ LibraryManager.library = { var aliasesBuf = _malloc(4); {{{ makeSetValue('aliasesBuf', '0', '0', 'i8*') }}} {{{ makeSetValue('ret', '___hostent_struct_layout.h_aliases', 'aliasesBuf', 'i8**') }}} - var afinet = {{{ cDefine("AF_INET") }}}; + var afinet = {{{ cDefine('AF_INET') }}}; {{{ makeSetValue('ret', '___hostent_struct_layout.h_addrtype', 'afinet', 'i32') }}} {{{ makeSetValue('ret', '___hostent_struct_layout.h_length', '4', 'i32') }}} var addrListBuf = _malloc(12); diff --git a/src/library_gl.js b/src/library_gl.js index c134ad97..16ea5531 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -657,6 +657,20 @@ var LibraryGL = { glBufferData__sig: 'viiii', glBufferData: function(target, size, data, usage) { + switch (usage) { // fix usages, WebGL only has *_DRAW + case 0x88E1: // GL_STREAM_READ + case 0x88E2: // GL_STREAM_COPY + usage = 0x88E0; // GL_STREAM_DRAW + break; + case 0x88E5: // GL_STATIC_READ + case 0x88E6: // GL_STATIC_COPY + usage = 0x88E4; // GL_STATIC_DRAW + break; + case 0x88E9: // GL_DYNAMIC_READ + case 0x88EA: // GL_DYNAMIC_COPY + usage = 0x88E8; // GL_DYNAMIC_DRAW + break; + } Module.ctx.bufferData(target, HEAPU8.subarray(data, data+size), usage); }, @@ -3398,6 +3412,7 @@ var LibraryGL = { // does not work for glBegin/End, where we generate renderer components dynamically and then // disable them ourselves, but it does help with glDrawElements/Arrays. if (!this.modifiedClientAttributes) { + GL.immediate.vertexCounter = (GL.immediate.stride * count) / 4; // XXX assuming float return; } this.modifiedClientAttributes = false; diff --git a/src/library_openal.js b/src/library_openal.js index dea986f3..e8a2e223 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -8,12 +8,6 @@ var LibraryOpenAL = { QUEUE_INTERVAL: 25, QUEUE_LOOKAHEAD: 100, - getCurrentTime: function(context) { - // currentTime is frozen during execution, use performance timers to - // emulate the current time at call time - return (window['performance']['now']() - context.startTime) / 1000.0; - }, - updateSources: function(context) { for (var i = 0; i < context.src.length; i++) { AL.updateSource(context.src[i]); @@ -28,7 +22,7 @@ var LibraryOpenAL = { return; } - var currentTime = AL.getCurrentTime(AL.currentContext); + var currentTime = AL.currentContext.ctx.currentTime; var startTime = src.bufferPosition; for (var i = src.buffersPlayed; i < src.queue.length; i++) { @@ -79,7 +73,7 @@ var LibraryOpenAL = { if (src.state !== 0x1013 /* AL_PAUSED */) { src.state = 0x1012 /* AL_PLAYING */; // Reset our position. - src.bufferPosition = AL.getCurrentTime(AL.currentContext); + src.bufferPosition = AL.currentContext.ctx.currentTime; src.buffersPlayed = 0; #if OPENAL_DEBUG console.log('setSourceState resetting and playing source ' + idx); @@ -87,7 +81,7 @@ var LibraryOpenAL = { } else { src.state = 0x1012 /* AL_PLAYING */; // Use the current offset from src.bufferPosition to resume at the correct point. - src.bufferPosition = AL.getCurrentTime(AL.currentContext) - src.bufferPosition; + src.bufferPosition = AL.currentContext.ctx.currentTime - src.bufferPosition; #if OPENAL_DEBUG console.log('setSourceState resuming source ' + idx + ' at ' + src.bufferPosition.toFixed(4)); #endif @@ -98,7 +92,7 @@ var LibraryOpenAL = { if (src.state === 0x1012 /* AL_PLAYING */) { src.state = 0x1013 /* AL_PAUSED */; // Store off the current offset to restore with on resume. - src.bufferPosition = AL.getCurrentTime(AL.currentContext) - src.bufferPosition; + src.bufferPosition = AL.currentContext.ctx.currentTime - src.bufferPosition; AL.stopSourceQueue(src); #if OPENAL_DEBUG console.log('setSourceState pausing source ' + idx + ' at ' + src.bufferPosition.toFixed(4)); @@ -212,8 +206,7 @@ var LibraryOpenAL = { err: 0, src: [], buf: [], - interval: setInterval(function() { AL.updateSources(context); }, AL.QUEUE_INTERVAL), - startTime: window['performance']['now']() + interval: setInterval(function() { AL.updateSources(context); }, AL.QUEUE_INTERVAL) }; AL.contexts.push(context); return AL.contexts.length; diff --git a/src/parseTools.js b/src/parseTools.js index 66354dca..90c5acab 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -35,8 +35,13 @@ function preprocess(text) { var op = parts[2]; var value = parts[3]; if (op) { - assert(op === '==') - showStack.push(ident in this && this[ident] == value); + if (op === '==') { + showStack.push(ident in this && this[ident] == value); + } else if (op === '!=') { + showStack.push(!(ident in this && this[ident] == value)); + } else { + error('unsupported preprecessor op ' + op); + } } else { showStack.push(ident in this && this[ident] > 0); } diff --git a/tests/gl_vertex_buffer.c b/tests/gl_vertex_buffer.c new file mode 100644 index 00000000..6b695462 --- /dev/null +++ b/tests/gl_vertex_buffer.c @@ -0,0 +1,195 @@ +/******************************************************************* + * * + * Using SDL With OpenGL * + * * + * Tutorial by Kyle Foley (sdw) * + * * + * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL * + * * + *******************************************************************/ + +/* + THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION + AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN. + + THE ORIGINAL AUTHOR IS KYLE FOLEY. + + THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY + OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF + MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, + ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE + RESULTING FROM THE USE, MODIFICATION, OR + REDISTRIBUTION OF THIS SOFTWARE. + */ + +#if !EMSCRIPTEN +#define USE_GLEW 0 +#endif + +#if USE_GLEW +#include "GL/glew.h" +#endif + +#include <SDL/SDL.h> + +#if !USE_GLEW +#include "SDL/SDL_opengl.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + + // Slightly different SDL initialization + if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) { + printf("Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } + + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new* + + screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed* + if ( !screen ) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + // Set the OpenGL state after creating the context with SDL_SetVideoMode + + glClearColor( 0, 0, 0, 0 ); + +#if !EMSCRIPTEN + glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL +#endif + + glViewport( 0, 0, 640, 480 ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + // Clear the screen before drawing + glClear( GL_COLOR_BUFFER_BIT ); + + typedef struct Color { + GLubyte r; + GLubyte g; + GLubyte b; + GLubyte a; + } Color; + + typedef struct Vertex { + GLfloat x; + GLfloat y; + Color color; + } Vertex; + + Vertex vertices[18] = { + {-1.00, 0.0, {0xFF, 0x00, 0xFF, 0xFF}}, + {-1.00, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.75, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.75, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + {-0.50, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.50, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.25, 0.0, {0xFF, 0x00, 0xFF, 0xFF}}, + {-0.25, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.00, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.00, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + { 0.25, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 0.25, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}, + { 0.50, 0.0, {0xFF, 0x00, 0xFF, 0xFF}}, + { 0.50, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}, + { 0.75, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 0.75, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + { 1.00, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 1.00, 1.0, {0xFF, 0xFF, 0x00, 0xFF}} + }; + + Vertex vertices2[18] = { + {-1.00, -1.0, {0xFF, 0x00, 0xFF, 0xFF}}, + {-1.00, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.75, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.75, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + {-0.50, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.50, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.25, -1.0, {0xFF, 0x00, 0xFF, 0xFF}}, + {-0.25, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.00, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.00, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + { 0.25, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 0.25, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}, + { 0.50, -1.0, {0xFF, 0x00, 0xFF, 0xFF}}, + { 0.50, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}, + { 0.75, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 0.75, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + { 1.00, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 1.00, 0.0, {0xFF, 0xFF, 0x00, 0xFF}} + }; + + // make a vertex buffer for the second set of vertices + GLuint vbo = 0; + glGenBuffers(1, &vbo); + + + // bind to it + glBindBuffer(GL_ARRAY_BUFFER, vbo); + // send it to gl + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_READ); // GL_STATIC_READ is not in WebGL! + + // unbind from it + glBindBuffer(GL_ARRAY_BUFFER, 0); + + + // DRAW + + // Clear the screen before drawing + glClear( GL_COLOR_BUFFER_BIT ); + + // This test ensures that we can use two separate arrays in memory for different + // attributes, and that they each can have different stride. + // The first test shows implicit striding (the zero indicates tightly packed) + // The second test shows explicit striding where the stride is passed in + // even though it also is tightly packed + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + // TEST 1 - clientside data + + glVertexPointer(2, GL_FLOAT, sizeof(Vertex), vertices); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vertices[0].color); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 6); + glDrawArrays(GL_TRIANGLE_STRIP, 10, 3); + + + + // TEST 2 - bind to array buffer, gl*Pointer calls are offsets into the buffer, which was previously uploaded to + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + + glVertexPointer(2, GL_FLOAT, sizeof(Vertex), 0); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), (GLvoid*)((GLvoid*)&vertices2[0].color - (GLvoid*)&vertices2[0])); + +// gldrawarrays first with a low number of vertices, then with a high number + glDrawArrays(GL_TRIANGLE_STRIP, 0, 6); + glDrawArrays(GL_TRIANGLE_STRIP, 10, 3); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + SDL_GL_SwapBuffers(); + +#if !EMSCRIPTEN + // Wait for 3 seconds to give us a chance to see the image + SDL_Delay(3000); +#endif + + SDL_Quit(); + + return 0; +} diff --git a/tests/gl_vertex_buffer.png b/tests/gl_vertex_buffer.png Binary files differnew file mode 100644 index 00000000..3e1f2230 --- /dev/null +++ b/tests/gl_vertex_buffer.png diff --git a/tests/gl_vertex_buffer_pre.c b/tests/gl_vertex_buffer_pre.c new file mode 100644 index 00000000..84b76569 --- /dev/null +++ b/tests/gl_vertex_buffer_pre.c @@ -0,0 +1,177 @@ +/******************************************************************* + * * + * Using SDL With OpenGL * + * * + * Tutorial by Kyle Foley (sdw) * + * * + * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL * + * * + *******************************************************************/ + +/* + THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION + AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN. + + THE ORIGINAL AUTHOR IS KYLE FOLEY. + + THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY + OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF + MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, + ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE + RESULTING FROM THE USE, MODIFICATION, OR + REDISTRIBUTION OF THIS SOFTWARE. + */ + +#if !EMSCRIPTEN +#define USE_GLEW 0 +#endif + +#if USE_GLEW +#include "GL/glew.h" +#endif + +#include <SDL/SDL.h> + +#if !USE_GLEW +#include "SDL/SDL_opengl.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + + // Slightly different SDL initialization + if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) { + printf("Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } + + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new* + + screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed* + if ( !screen ) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + // Set the OpenGL state after creating the context with SDL_SetVideoMode + + glClearColor( 0, 0, 0, 0 ); + +#if !EMSCRIPTEN + glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL +#endif + + glViewport( 0, 0, 640, 480 ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + // Clear the screen before drawing + glClear( GL_COLOR_BUFFER_BIT ); + + typedef struct Color { + GLubyte r; + GLubyte g; + GLubyte b; + GLubyte a; + } Color; + + typedef struct Vertex { + GLfloat x; + GLfloat y; + Color color; + } Vertex; + + Vertex vertices[18] = { + {-1.00, 0.0, {0xFF, 0x00, 0xFF, 0xFF}}, + {-1.00, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.75, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.75, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + {-0.50, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.50, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.25, 0.0, {0xFF, 0x00, 0xFF, 0xFF}}, + {-0.25, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.00, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.00, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + { 0.25, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 0.25, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}, + { 0.50, 0.0, {0xFF, 0x00, 0xFF, 0xFF}}, + { 0.50, 1.0, {0xFF, 0xFF, 0x00, 0xFF}}, + { 0.75, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 0.75, 1.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + { 1.00, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 1.00, 1.0, {0xFF, 0xFF, 0x00, 0xFF}} + }; + + Vertex vertices2[18] = { + {-1.00, -1.0, {0xFF, 0x00, 0xFF, 0xFF}}, + {-1.00, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.75, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.75, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + {-0.50, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.50, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.25, -1.0, {0xFF, 0x00, 0xFF, 0xFF}}, + {-0.25, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}, + {-0.00, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + {-0.00, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + { 0.25, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 0.25, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}, + { 0.50, -1.0, {0xFF, 0x00, 0xFF, 0xFF}}, + { 0.50, 0.0, {0xFF, 0xFF, 0x00, 0xFF}}, + { 0.75, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 0.75, 0.0, {0xFF, 0xFF, 0xFF, 0xFF}}, + { 1.00, -1.0, {0xFF, 0x00, 0x00, 0xFF}}, + { 1.00, 0.0, {0xFF, 0xFF, 0x00, 0xFF}} + }; + + // make a vertex buffer for the second set of vertices + GLuint vbo = 0; + glGenBuffers(1, &vbo); + + + // bind to it + glBindBuffer(GL_ARRAY_BUFFER, vbo); + // send it to gl + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW); + + // unbind from it + glBindBuffer(GL_ARRAY_BUFFER, 0); + + + // DRAW + + // Clear the screen before drawing + glClear( GL_COLOR_BUFFER_BIT ); + + // This test ensures that we can use two separate arrays in memory for different + // attributes, and that they each can have different stride. + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(2, GL_FLOAT, sizeof(Vertex), vertices); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &vertices[0].color); + glDrawArrays(GL_TRIANGLE_STRIP, 10, 3); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 6); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + SDL_GL_SwapBuffers(); + +#if !EMSCRIPTEN + // Wait for 3 seconds to give us a chance to see the image + SDL_Delay(3000); +#endif + + SDL_Quit(); + + return 0; +} diff --git a/tests/gl_vertex_buffer_pre.png b/tests/gl_vertex_buffer_pre.png Binary files differnew file mode 100644 index 00000000..5677a868 --- /dev/null +++ b/tests/gl_vertex_buffer_pre.png diff --git a/tests/test_browser.py b/tests/test_browser.py index b014b4f6..3ac640f1 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1207,6 +1207,12 @@ If manually bisecting: def test_gl_stride(self): self.btest('gl_stride.c', reference='gl_stride.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1']) + def test_gl_vertex_buffer_pre(self): + self.btest('gl_vertex_buffer_pre.c', reference='gl_vertex_buffer_pre.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1']) + + def test_gl_vertex_buffer(self): + self.btest('gl_vertex_buffer.c', reference='gl_vertex_buffer.png', args=['-s', 'GL_UNSAFE_OPTS=0', '-s', 'LEGACY_GL_EMULATION=1'], reference_slack=1) + def test_matrix_identity(self): self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840'], args=['-s', 'LEGACY_GL_EMULATION=1']) diff --git a/tests/test_core.py b/tests/test_core.py index 6bb5ccb6..ff768b5c 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5751,8 +5751,8 @@ def process(filename): if Settings.ASM_JS and os.path.exists(SPIDERMONKEY_ENGINE[0]): out = run_js('liblib.so', engine=SPIDERMONKEY_ENGINE, full_output=True, stderr=STDOUT) - assert 'asm' in out - self.validate_asmjs(out) + if 'asm' in out: + self.validate_asmjs(out) def test_dlfcn_data_and_fptr(self): if Settings.ASM_JS: return self.skip('this is not a valid case - libraries should not be able to access their parents globals willy nilly') @@ -6226,6 +6226,139 @@ ok Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free'] self.do_run(src, '''*294,153*''', force_c=True, post_build=self.dlfcn_post_build) + def test_dlfcn_longjmp(self): + if not self.can_dlfcn(): return + + self.prep_dlfcn_lib() + lib_src = r''' + #include <setjmp.h> + + void jumpy(jmp_buf buf) { + static int i = 0; + i++; + if (i == 10) longjmp(buf, i); + printf("pre %d\n", i); + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_jumpy'] + dirname = self.get_dir() + filename = os.path.join(dirname, 'liblib.c') + self.build(lib_src, dirname, filename) + shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) + + self.prep_dlfcn_main() + src = r''' + #include <assert.h> + #include <stdio.h> + #include <dlfcn.h> + #include <setjmp.h> + + typedef void (*jumpfunc)(jmp_buf); + + int main() { + printf("go!\n"); + + void *lib_handle; + lib_handle = dlopen("liblib.so", RTLD_NOW); + assert(lib_handle != NULL); + + jumpfunc jumpy = (jumpfunc)dlsym(lib_handle, "jumpy"); + assert(jumpy); + + jmp_buf buf; + int jmpval = setjmp(buf); + if (jmpval == 0) { + while (1) jumpy(buf); + } else { + printf("out!\n"); + } + + return 0; + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free'] + self.do_run(src, '''go! +pre 1 +pre 2 +pre 3 +pre 4 +pre 5 +pre 6 +pre 7 +pre 8 +pre 9 +out! +''', post_build=self.dlfcn_post_build, force_c=True) + + def zzztest_dlfcn_exceptions(self): # TODO: make this work. need to forward tempRet0 across modules + if not self.can_dlfcn(): return + + Settings.DISABLE_EXCEPTION_CATCHING = 0 + + self.prep_dlfcn_lib() + lib_src = r''' + extern "C" { + int ok() { + return 65; + } + int fail() { + throw 123; + } + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_ok', '_fail'] + dirname = self.get_dir() + filename = os.path.join(dirname, 'liblib.cpp') + self.build(lib_src, dirname, filename) + shutil.move(filename + '.o.js', os.path.join(dirname, 'liblib.so')) + + self.prep_dlfcn_main() + src = r''' + #include <assert.h> + #include <stdio.h> + #include <dlfcn.h> + + typedef int (*intfunc)(); + + int main() { + printf("go!\n"); + + void *lib_handle; + lib_handle = dlopen("liblib.so", RTLD_NOW); + assert(lib_handle != NULL); + + intfunc okk = (intfunc)dlsym(lib_handle, "ok"); + intfunc faill = (intfunc)dlsym(lib_handle, "fail"); + assert(okk && faill); + + try { + printf("ok: %d\n", okk()); + } catch(...) { + printf("wha\n"); + } + + try { + printf("fail: %d\n", faill()); + } catch(int x) { + printf("int %d\n", x); + } + + try { + printf("fail: %d\n", faill()); + } catch(double x) { + printf("caught %f\n", x); + } + + return 0; + } + ''' + Settings.EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free'] + self.do_run(src, '''go! +ok: 65 +int 123 +ok +''', post_build=self.dlfcn_post_build) + def test_rand(self): return self.skip('rand() is now random') # FIXME diff --git a/tools/shared.py b/tools/shared.py index 8fdb52a5..2e11d736 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -283,6 +283,20 @@ def check_node_version(): logging.warning('cannot check node version: %s', e) return False +# Finds the system temp directory without resorting to using the one configured in .emscripten +def find_temp_directory(): + if WINDOWS: + if os.getenv('TEMP') and os.path.isdir(os.getenv('TEMP')): + return os.getenv('TEMP') + elif os.getenv('TMP') and os.path.isdir(os.getenv('TMP')): + return os.getenv('TMP') + elif os.path.isdir('C:\\temp'): + return os.getenv('C:\\temp') + else: + return None # No luck! + else: + return '/tmp' + # Check that basic stuff we need (a JS engine to compile, Node.js, and Clang and LLVM) # exists. # The test runner always does this check (through |force|). emcc does this less frequently, @@ -450,8 +464,13 @@ class Configuration: try: self.TEMP_DIR = TEMP_DIR except NameError: - logging.debug('TEMP_DIR not defined in ~/.emscripten, using /tmp') - self.TEMP_DIR = '/tmp' + self.TEMP_DIR = find_temp_directory() + if self.TEMP_DIR == None: + logging.critical('TEMP_DIR not defined in ' + os.path.expanduser('~\\.emscripten') + ", and could not detect a suitable directory! Please configure .emscripten to contain a variable TEMP_DIR='/path/to/temp/dir'.") + logging.debug('TEMP_DIR not defined in ~/.emscripten, using ' + self.TEMP_DIR) + + if not os.path.isdir(self.TEMP_DIR): + logging.critical("The temp directory TEMP_DIR='" + self.TEMP_DIR + "' doesn't seem to exist! Please make sure that the path is correct.") self.CANONICAL_TEMP_DIR = os.path.join(self.TEMP_DIR, 'emscripten_temp') @@ -469,12 +488,13 @@ class Configuration: save_debug_files=os.environ.get('EMCC_DEBUG_SAVE')) def apply_configuration(): - global configuration, DEBUG, EMSCRIPTEN_TEMP_DIR, DEBUG_CACHE, CANONICAL_TEMP_DIR + global configuration, DEBUG, EMSCRIPTEN_TEMP_DIR, DEBUG_CACHE, CANONICAL_TEMP_DIR, TEMP_DIR configuration = Configuration() DEBUG = configuration.DEBUG EMSCRIPTEN_TEMP_DIR = configuration.EMSCRIPTEN_TEMP_DIR DEBUG_CACHE = configuration.DEBUG_CACHE CANONICAL_TEMP_DIR = configuration.CANONICAL_TEMP_DIR + TEMP_DIR = configuration.TEMP_DIR apply_configuration() logging.basicConfig(format='%(levelname)-8s %(name)s: %(message)s') |