diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-06-16 14:40:45 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-06-16 14:40:45 -0700 |
commit | ba387574f23867d889a04f1586e6dd9597e8bad8 (patch) | |
tree | 6934000fdd9c173c552a382676b5046f58877b26 /src | |
parent | 7acb48826165890ebc9d3794d8d7473aa62b762e (diff) | |
parent | 7c26bbdb7d3c40d68777cc93f54ebfa5355a48bc (diff) |
Merge branch 'incoming' into proxyGL
Diffstat (limited to 'src')
-rw-r--r-- | src/deps_info.json | 1 | ||||
-rw-r--r-- | src/deterministic.js (renamed from src/determinstic.js) | 7 | ||||
-rw-r--r-- | src/jsifier.js | 5 | ||||
-rw-r--r-- | src/library.js | 13 | ||||
-rw-r--r-- | src/library_browser.js | 33 | ||||
-rw-r--r-- | src/library_fs.js | 13 | ||||
-rw-r--r-- | src/library_glfw.js | 7 | ||||
-rw-r--r-- | src/library_idbfs.js | 3 | ||||
-rw-r--r-- | src/library_memfs.js | 168 | ||||
-rw-r--r-- | src/library_sdl.js | 57 | ||||
-rw-r--r-- | src/modules.js | 25 | ||||
-rw-r--r-- | src/settings.js | 7 |
12 files changed, 270 insertions, 69 deletions
diff --git a/src/deps_info.json b/src/deps_info.json index 029a20e1..e0983064 100644 --- a/src/deps_info.json +++ b/src/deps_info.json @@ -3,6 +3,7 @@ "SDL_Init": ["malloc", "free"], "SDL_GL_GetProcAddress": ["emscripten_GetProcAddress"], "eglGetProcAddress": ["emscripten_GetProcAddress"], + "glfwGetProcAddress": ["emscripten_GetProcAddress"], "emscripten_GetProcAddress": ["strstr"] } diff --git a/src/determinstic.js b/src/deterministic.js index 1ec0bbfe..4e9508f3 100644 --- a/src/determinstic.js +++ b/src/deterministic.js @@ -8,13 +8,14 @@ var TIME = 10000; Date.now = function() { return TIME++; }; -performance.now = Date.now; +if (typeof performance === 'object') performance.now = Date.now; function hashMemory(id) { var ret = 0; - for (var i = 0; i < HEAPU8.length; i++) { + var len = Math.max(DYNAMICTOP, STATICTOP); + for (var i = 0; i < len; i++) { ret = (ret*17 + HEAPU8[i])|0; } - print(id + ':' + ret); + printErr(id + ':' + ret); } diff --git a/src/jsifier.js b/src/jsifier.js index e35fef1a..1f6440dd 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -370,7 +370,7 @@ function JSify(data, functionsOnly) { // name the function; overwrite if it's already named snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '('); - if (LIBRARY_DEBUG) { + if (LIBRARY_DEBUG && !LibraryManager.library[ident + '__asm']) { snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); '); snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.printErr(" [ return:" + Runtime.prettyPrint(ret)); return ret; \n}'; } @@ -1902,6 +1902,9 @@ function JSify(data, functionsOnly) { print(read('webGLWorker.js')); print(read('proxyWorker.js')); } + if (DETERMINISTIC) { + print(read('deterministic.js')); + } if (RUNTIME_TYPE_INFO) { Types.cleanForRuntime(); print('Runtime.typeInfo = ' + JSON.stringify(Types.types)); diff --git a/src/library.js b/src/library.js index c17952b3..1f7fd37d 100644 --- a/src/library.js +++ b/src/library.js @@ -3166,7 +3166,7 @@ LibraryManager.library = { #endif environ: 'allocate(1, "i32*", ALLOC_STATIC)', __environ__deps: ['environ'], - __environ: '_environ', + __environ: 'environ', __buildEnvironment__deps: ['__environ'], __buildEnvironment: function(env) { // WARNING: Arbitrary limit! @@ -3388,9 +3388,20 @@ LibraryManager.library = { memcpy__sig: 'iiii', memcpy__deps: ['emscripten_memcpy_big'], memcpy: function(dest, src, num) { +#if USE_TYPED_ARRAYS == 0 + {{{ makeCopyValues('dest', 'src', 'num', 'null') }}}; + return num; +#endif +#if USE_TYPED_ARRAYS == 1 + {{{ makeCopyValues('dest', 'src', 'num', 'null') }}}; + return num; +#endif + dest = dest|0; src = src|0; num = num|0; var ret = 0; +#if USE_TYPED_ARRAYS if ((num|0) >= 4096) return _emscripten_memcpy_big(dest|0, src|0, num|0)|0; +#endif ret = dest|0; if ((dest&3) == (src&3)) { while (dest & 3) { diff --git a/src/library_browser.js b/src/library_browser.js index 8509c9d7..8e86371e 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -1175,6 +1175,39 @@ mergeInto(LibraryManager.library, { var info = Browser.workers[id]; if (!info) return -1; return info.awaited; + }, + + emscripten_get_preloaded_image_data: function(path, w, h) { + if (typeof path === "number") { + path = Pointer_stringify(path); + } + + path = PATH.resolve(path); + + var canvas = Module["preloadedImages"][path]; + if (canvas) { + var ctx = canvas.getContext("2d"); + var image = ctx.getImageData(0, 0, canvas.width, canvas.height); + var buf = _malloc(canvas.width * canvas.height * 4); + + HEAPU8.set(image.data, buf); + + {{{ makeSetValue('w', '0', 'canvas.width', 'i32') }}}; + {{{ makeSetValue('h', '0', 'canvas.height', 'i32') }}}; + return buf; + } + + return 0; + }, + + emscripten_get_preloaded_image_data_from_FILE__deps: ['emscripten_get_preloaded_image_data'], + emscripten_get_preloaded_image_data_from_FILE: function(file, w, h) { + var stream = FS.getStreamFromPtr(file); + if (stream) { + return _emscripten_get_preloaded_image_data(stream.path, w, h); + } + + return 0; } }); diff --git a/src/library_fs.js b/src/library_fs.js index 5f7f1dea..d825892c 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -1077,6 +1077,10 @@ mergeInto(LibraryManager.library, { if (!stream.stream_ops.write) { throw new FS.ErrnoError(ERRNO_CODES.EINVAL); } + if (stream.flags & {{{ cDefine('O_APPEND') }}}) { + // seek to the end before writing in append mode + FS.llseek(stream, 0, {{{ cDefine('SEEK_END') }}}); + } var seeking = true; if (typeof position === 'undefined') { position = stream.position; @@ -1084,10 +1088,6 @@ mergeInto(LibraryManager.library, { } else if (!stream.seekable) { throw new FS.ErrnoError(ERRNO_CODES.ESPIPE); } - if (stream.flags & {{{ cDefine('O_APPEND') }}}) { - // seek to the end before writing in append mode - FS.llseek(stream, 0, {{{ cDefine('SEEK_END') }}}); - } var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn); if (!seeking) stream.position += bytesWritten; try { @@ -1480,6 +1480,7 @@ mergeInto(LibraryManager.library, { // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as // read() will try to parse UTF8. obj.contents = intArrayFromString(Module['read'](obj.url), true); + obj.usedBytes = obj.contents.length; } catch (e) { success = false; } @@ -1601,6 +1602,10 @@ mergeInto(LibraryManager.library, { node.contents = null; node.url = properties.url; } + // Add a function that defers querying the file size until it is asked the first time. + Object.defineProperty(node, "usedBytes", { + get: function() { return this.contents.length; } + }); // override each stream op with one that tries to force load the lazy file first var stream_ops = {}; var keys = Object.keys(node.stream_ops); diff --git a/src/library_glfw.js b/src/library_glfw.js index 6d539326..6dfea101 100644 --- a/src/library_glfw.js +++ b/src/library_glfw.js @@ -417,6 +417,9 @@ var LibraryGLFW = { glfwSetWindowSizeCallback: function(cbfun) { GLFW.resizeFunc = cbfun; + if (GLFW.resizeFunc) { + Runtime.dynCall('vii', GLFW.resizeFunc, [Module['canvas'].width, Module['canvas'].height]); + } }, glfwSetWindowCloseCallback: function(cbfun) { @@ -507,9 +510,9 @@ var LibraryGLFW = { return Module.ctx.getSupportedExtensions().indexOf(Pointer_stringify(extension)) > -1; }, - glfwGetProcAddress__deps: ['glfwGetProcAddress'], + glfwGetProcAddress__deps: ['emscripten_GetProcAddress'], glfwGetProcAddress: function(procname) { - return _getProcAddress(procname); + return _emscripten_GetProcAddress(procname); }, glfwGetGLVersion: function(major, minor, rev) { diff --git a/src/library_idbfs.js b/src/library_idbfs.js index 91015e77..8082c196 100644 --- a/src/library_idbfs.js +++ b/src/library_idbfs.js @@ -135,6 +135,9 @@ mergeInto(LibraryManager.library, { if (FS.isDir(stat.mode)) { return callback(null, { timestamp: stat.mtime, mode: stat.mode }); } else if (FS.isFile(stat.mode)) { + // Performance consideration: storing a normal JavaScript array to a IndexedDB is much slower than storing a typed array. + // Therefore always convert the file contents to a typed array first before writing the data to IndexedDB. + node.contents = MEMFS.getFileDataAsTypedArray(node); return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents }); } else { return callback(new Error('node type not supported')); diff --git a/src/library_memfs.js b/src/library_memfs.js index 95c3ae65..72ecdcfe 100644 --- a/src/library_memfs.js +++ b/src/library_memfs.js @@ -2,11 +2,6 @@ mergeInto(LibraryManager.library, { $MEMFS__deps: ['$FS'], $MEMFS: { ops_table: null, - - // content modes - CONTENT_OWNING: 1, // contains a subarray into the heap, and we own it, without copying (note: someone else needs to free() it, if that is necessary) - CONTENT_FLEXIBLE: 2, // has been modified or never set to anything, and is a flexible js array that can grow/shrink - CONTENT_FIXED: 3, // contains some fixed-size content written into it, in a typed array mount: function(mount) { return MEMFS.createNode(null, '/', {{{ cDefine('S_IFDIR') }}} | 511 /* 0777 */, 0); }, @@ -71,8 +66,11 @@ mergeInto(LibraryManager.library, { } else if (FS.isFile(node.mode)) { node.node_ops = MEMFS.ops_table.file.node; node.stream_ops = MEMFS.ops_table.file.stream; - node.contents = []; - node.contentMode = MEMFS.CONTENT_FLEXIBLE; + node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.buffer.byteLength which gives the whole capacity. + // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred + // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size + // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme. + node.contents = null; } else if (FS.isLink(node.mode)) { node.node_ops = MEMFS.ops_table.link.node; node.stream_ops = MEMFS.ops_table.link.stream; @@ -87,13 +85,88 @@ mergeInto(LibraryManager.library, { } return node; }, - ensureFlexible: function(node) { - if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) { - var contents = node.contents; - node.contents = Array.prototype.slice.call(contents); - node.contentMode = MEMFS.CONTENT_FLEXIBLE; + + // Given a file node, returns its file data converted to a regular JS array. You should treat this as read-only. + getFileDataAsRegularArray: function(node) { +#if USE_TYPED_ARRAYS == 2 + if (node.contents && node.contents.subarray) { + var arr = []; + for (var i = 0; i < node.usedBytes; ++i) arr.push(node.contents[i]); + return arr; // Returns a copy of the original data. + } +#endif + return node.contents; // No-op, the file contents are already in a JS array. Return as-is. + }, + +#if USE_TYPED_ARRAYS == 2 + // Given a file node, returns its file data converted to a typed array. + getFileDataAsTypedArray: function(node) { + if (node.contents && node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes. + return new Uint8Array(node.contents); + }, +#endif + + // Allocates a new backing store for the given node so that it can fit at least newSize amount of bytes. + // May allocate more, to provide automatic geometric increase and amortized linear performance appending writes. + // Never shrinks the storage. + expandFileStorage: function(node, newCapacity) { +#if USE_TYPED_ARRAYS == 2 + +#if !MEMFS_APPEND_TO_TYPED_ARRAYS + // If we are asked to expand the size of a file that already exists, revert to using a standard JS array to store the file + // instead of a typed array. This makes resizing the array more flexible because we can just .push() elements at the back to + // increase the size. + if (node.contents && node.contents.subarray && newCapacity > node.contents.length) { + node.contents = MEMFS.getFileDataAsRegularArray(node); + node.usedBytes = node.contents.length; // We might be writing to a lazy-loaded file which had overridden this property, so force-reset it. + } +#endif + + if (!node.contents || node.contents.subarray) { // Keep using a typed array if creating a new storage, or if old one was a typed array as well. + var prevCapacity = node.contents ? node.contents.buffer.byteLength : 0; + if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough. + // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity. + // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to + // avoid overshooting the allocation cap by a very large margin. + var CAPACITY_DOUBLING_MAX = 1024 * 1024; + newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) | 0); + if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding. + var oldContents = node.contents; + node.contents = new Uint8Array(newCapacity); // Allocate new storage. + if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage. + return; + } +#endif + // Not using a typed array to back the file storage. Use a standard JS array instead. + if (!node.contents && newCapacity > 0) node.contents = []; + while (node.contents.length < newCapacity) node.contents.push(0); + }, + + // Performs an exact resize of the backing file storage to the given size, if the size is not exactly this, the storage is fully reallocated. + resizeFileStorage: function(node, newSize) { + if (node.usedBytes == newSize) return; + if (newSize == 0) { + node.contents = null; // Fully decommit when requesting a resize to zero. + node.usedBytes = 0; + return; } + +#if USE_TYPED_ARRAYS == 2 + if (!node.contents || node.contents.subarray) { // Resize a typed array if that is being used as the backing store. + var oldContents = node.contents; + node.contents = new Uint8Array(new ArrayBuffer(newSize)); // Allocate new storage. + node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage. + node.usedBytes = newSize; + return; + } +#endif + // Backing with a JS array. + if (!node.contents) node.contents = []; + if (node.contents.length > newSize) node.contents.length = newSize; + else while (node.contents.length < newSize) node.contents.push(0); + node.usedBytes = newSize; }, + node_ops: { getattr: function(node) { var attr = {}; @@ -108,7 +181,7 @@ mergeInto(LibraryManager.library, { if (FS.isDir(node.mode)) { attr.size = 4096; } else if (FS.isFile(node.mode)) { - attr.size = node.contents.length; + attr.size = node.usedBytes; } else if (FS.isLink(node.mode)) { attr.size = node.link.length; } else { @@ -131,10 +204,7 @@ mergeInto(LibraryManager.library, { node.timestamp = attr.timestamp; } if (attr.size !== undefined) { - MEMFS.ensureFlexible(node); - var contents = node.contents; - if (attr.size < contents.length) contents.length = attr.size; - else while (attr.size > contents.length) contents.push(0); + MEMFS.resizeFileStorage(node, attr.size); } }, lookup: function(parent, name) { @@ -198,9 +268,8 @@ mergeInto(LibraryManager.library, { stream_ops: { read: function(stream, buffer, offset, length, position) { var contents = stream.node.contents; - if (position >= contents.length) - return 0; - var size = Math.min(contents.length - position, length); + if (position >= stream.node.usedBytes) return 0; + var size = Math.min(stream.node.usedBytes - position, length); assert(size >= 0); #if USE_TYPED_ARRAYS == 2 if (size > 8 && contents.subarray) { // non-trivial, and typed array @@ -208,47 +277,56 @@ mergeInto(LibraryManager.library, { } else #endif { - for (var i = 0; i < size; i++) { - buffer[offset + i] = contents[position + i]; - } + for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i]; } return size; }, + + // Writes the byte range (buffer[offset], buffer[offset+length]) to offset 'position' into the file pointed by 'stream' write: function(stream, buffer, offset, length, position, canOwn) { + if (!length) return 0; var node = stream.node; node.timestamp = Date.now(); - var contents = node.contents; + #if USE_TYPED_ARRAYS == 2 - if (length && contents.length === 0 && position === 0 && buffer.subarray) { - // just replace it with the new data + if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array? + if (canOwn) { // Can we just reuse the buffer we are given? #if ASSERTIONS - assert(buffer.length); + assert(position === 0, 'canOwn must imply no weird position inside the file'); #endif - if (canOwn && offset === 0) { - node.contents = buffer; // this could be a subarray of Emscripten HEAP, or allocated from some other source. - node.contentMode = (buffer.buffer === HEAP8.buffer) ? MEMFS.CONTENT_OWNING : MEMFS.CONTENT_FIXED; - } else { - node.contents = new Uint8Array(buffer.subarray(offset, offset+length)); - node.contentMode = MEMFS.CONTENT_FIXED; + node.contents = buffer.subarray(offset, offset + length); + node.usedBytes = length; + return length; + } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data. + node.contents = new Uint8Array(buffer.subarray(offset, offset + length)); + node.usedBytes = length; + return length; + } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file? + node.contents.set(buffer.subarray(offset, offset + length), position); + return length; } - return length; } #endif - MEMFS.ensureFlexible(node); - var contents = node.contents; - while (contents.length < position) contents.push(0); - for (var i = 0; i < length; i++) { - contents[position + i] = buffer[offset + i]; - } + // Appending to an existing file and we need to reallocate, or source data did not come as a typed array. + MEMFS.expandFileStorage(node, position+length); +#if USE_TYPED_ARRAYS == 2 + if (node.contents.subarray && buffer.subarray) node.contents.set(buffer.subarray(offset, offset + length), position); // Use typed array write if available. + else +#endif + for (var i = 0; i < length; i++) { + node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not. + } + node.usedBytes = Math.max(node.usedBytes, position+length); return length; }, + llseek: function(stream, offset, whence) { var position = offset; if (whence === 1) { // SEEK_CUR. position += stream.position; } else if (whence === 2) { // SEEK_END. if (FS.isFile(stream.node.mode)) { - position += stream.node.contents.length; + position += stream.node.usedBytes; } } if (position < 0) { @@ -259,10 +337,8 @@ mergeInto(LibraryManager.library, { return position; }, allocate: function(stream, offset, length) { - MEMFS.ensureFlexible(stream.node); - var contents = stream.node.contents; - var limit = offset + length; - while (limit > contents.length) contents.push(0); + MEMFS.expandFileStorage(stream.node, offset + length); + stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length); }, mmap: function(stream, buffer, offset, length, position, prot, flags) { if (!FS.isFile(stream.node.mode)) { @@ -280,7 +356,7 @@ mergeInto(LibraryManager.library, { ptr = contents.byteOffset; } else { // Try to avoid unnecessary slices. - if (position > 0 || position + length < contents.length) { + if (position > 0 || position + length < stream.node.usedBytes) { if (contents.subarray) { contents = contents.subarray(position, position + length); } else { diff --git a/src/library_sdl.js b/src/library_sdl.js index 35698279..104a0300 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -84,6 +84,9 @@ var LibrarySDL = { TOUCH_DEFAULT_ID: 0, // Our default deviceID for touch events (we get nothing from the browser) + eventHandler: null, + eventHandlerContext: null, + keyCodes: { // DOM code ==> SDL code. See https://developer.mozilla.org/en/Document_Object_Model_%28DOM%29/KeyboardEvent and SDL_keycode.h // For keys that don't have unicode value, we map DOM codes with the corresponding scan codes + 1024 (using "| 1 << 10") 16: 225 | 1<<10, // shift @@ -304,7 +307,12 @@ var LibrarySDL = { {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.pitch, 'width * bpp', 'i32') }}}; // assuming RGBA or indexed for now, // since that is what ImageData gives us in browsers {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.pixels, 'buffer', 'void*') }}}; - {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.clip_rect, '0', 'i32*') }}}; + + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.clip_rect+C_STRUCTS.SDL_Rect.x, '0', 'i32') }}}; + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.clip_rect+C_STRUCTS.SDL_Rect.y, '0', 'i32') }}}; + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.clip_rect+C_STRUCTS.SDL_Rect.w, 'Module["canvas"].width', 'i32') }}}; + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.clip_rect+C_STRUCTS.SDL_Rect.h, 'Module["canvas"].height', 'i32') }}}; + {{{ makeSetValue('surf', C_STRUCTS.SDL_Surface.refcount, '1', 'i32') }}}; {{{ makeSetValue('pixelFormat', C_STRUCTS.SDL_PixelFormat.format, cDefine('SDL_PIXELFORMAT_RGBA8888'), 'i32') }}}; @@ -699,6 +707,9 @@ var LibrarySDL = { Module.printErr('SDL event queue full, dropping events'); SDL.events = SDL.events.slice(0, 10000); } + // If we have a handler installed, this will push the events to the app + // instead of the app polling for them. + SDL.flushEventsToHandler(); return; }, @@ -750,6 +761,30 @@ var LibrarySDL = { } }, + flushEventsToHandler: function() { + if (!SDL.eventHandler) return; + + // All SDLEvents take the same amount of memory + var sdlEventPtr = allocate({{{ C_STRUCTS.SDL_KeyboardEvent.__size__ }}}, "i8", ALLOC_STACK); + + while (SDL.pollEvent(sdlEventPtr)) { + Runtime.dynCall('iii', SDL.eventHandler, [SDL.eventHandlerContext, sdlEventPtr]); + } + }, + + pollEvent: function(ptr) { + if (SDL.initFlags & 0x200 && SDL.joystickEventState) { + // If SDL_INIT_JOYSTICK was supplied AND the joystick system is configured + // to automatically query for events, query for joystick events. + SDL.queryJoysticks(); + } + if (SDL.events.length === 0) return 0; + if (ptr) { + SDL.makeCEvent(SDL.events.shift(), ptr); + } + return 1; + }, + makeCEvent: function(event, ptr) { if (typeof event === 'number') { // This is a pointer to a native C event that was SDL_PushEvent'ed @@ -1715,16 +1750,7 @@ var LibrarySDL = { }, SDL_PollEvent: function(ptr) { - if (SDL.initFlags & 0x200 && SDL.joystickEventState) { - // If SDL_INIT_JOYSTICK was supplied AND the joystick system is configured - // to automatically query for events, query for joystick events. - SDL.queryJoysticks(); - } - if (SDL.events.length === 0) return 0; - if (ptr) { - SDL.makeCEvent(SDL.events.shift(), ptr); - } - return 1; + return SDL.pollEvent(ptr); }, SDL_PushEvent: function(ptr) { @@ -1764,6 +1790,13 @@ var LibrarySDL = { SDL.handleEvent(event); }); }, + + // An Emscripten-specific extension to SDL: Some browser APIs require that they are called from within an event handler function. + // Allow recording a callback that will be called for each received event. + emscripten_SDL_SetEventHandler: function(handler, userdata) { + SDL.eventHandler = handler; + SDL.eventHandlerContext = userdata; + }, SDL_SetColors: function(surf, colors, firstColor, nColors) { var surfData = SDL.surfaces[surf]; @@ -2607,7 +2640,7 @@ var LibrarySDL = { if (info && info.audio) { info.audio.pause(); } else { - Module.printErr('Mix_Pause: no sound found for channel: ' + channel); + //Module.printErr('Mix_Pause: no sound found for channel: ' + channel); } }, diff --git a/src/modules.js b/src/modules.js index fd5c23cd..56f4c827 100644 --- a/src/modules.js +++ b/src/modules.js @@ -443,6 +443,31 @@ var LibraryManager = { } } + // apply synonyms. these are typically not speed-sensitive, and doing it this way makes it possible to not include hacks in the compiler + // (and makes it simpler to switch between SDL verisons, fastcomp and non-fastcomp, etc.). + var lib = LibraryManager.library; + libloop: for (var x in lib) { + if (x.lastIndexOf('__') > 0) continue; // ignore __deps, __* + if (lib[x + '__asm']) continue; // ignore asm library functions, those need to be fully optimized + if (typeof lib[x] === 'string') { + var target = x; + while (typeof lib[target] === 'string') { + if (lib[target].indexOf('(') >= 0) continue libloop; + target = lib[target]; + } + if (typeof lib[target] === 'undefined' || typeof lib[target] === 'function') { + if (target.indexOf('Math_') < 0) { + lib[x] = new Function('return _' + target + '.apply(null, arguments)'); + if (!lib[x + '__deps']) lib[x + '__deps'] = []; + lib[x + '__deps'].push(target); + } else { + lib[x] = new Function('return ' + target + '.apply(null, arguments)'); + } + continue; + } + } + } + /* // export code for CallHandlers.h printErr('============================'); diff --git a/src/settings.js b/src/settings.js index bdb149e3..26883051 100644 --- a/src/settings.js +++ b/src/settings.js @@ -323,6 +323,10 @@ var FS_LOG = 0; // Log all FS operations. This is especially helpful when you'r // so that you can create a virtual file system with all of the required files. var CASE_INSENSITIVE_FS = 0; // If set to nonzero, the provided virtual filesystem if treated case-insensitive, like // Windows and OSX do. If set to 0, the VFS is case-sensitive, like on Linux. +var MEMFS_APPEND_TO_TYPED_ARRAYS = 0; // If set to nonzero, MEMFS will always utilize typed arrays as the backing store + // for appending data to files. The default behavior is to use typed arrays for files + // when the file size doesn't change after initial creation, and for files that do + // change size, use normal JS arrays instead. var USE_BSS = 1; // https://en.wikipedia.org/wiki/.bss // When enabled, 0-initialized globals are sorted to the end of the globals list, @@ -474,6 +478,9 @@ var HEADLESS = 0; // If 1, will include shim code that tries to 'fake' a browser // very partial - it is hard to fake a whole browser! - so // keep your expectations low for this to work. +var DETERMINISTIC = 0; // If 1, we force Date.now(), Math.random, etc. to return deterministic + // results. Good for comparing builds for debugging purposes (and nothing else) + var BENCHMARK = 0; // If 1, will just time how long main() takes to execute, and not // print out anything at all whatsoever. This is useful for benchmarking. |