diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler.js | 28 | ||||
-rw-r--r-- | src/intertyper.js | 25 | ||||
-rw-r--r-- | src/jsifier.js | 38 | ||||
-rw-r--r-- | src/library.js | 104 | ||||
-rw-r--r-- | src/library_browser.js | 19 | ||||
-rw-r--r-- | src/library_gl.js | 837 | ||||
-rw-r--r-- | src/library_sdl.js | 29 | ||||
-rw-r--r-- | src/library_sockfs.js | 2 | ||||
-rw-r--r-- | src/modules.js | 6 | ||||
-rw-r--r-- | src/parseTools.js | 34 | ||||
-rw-r--r-- | src/preamble.js | 18 | ||||
-rw-r--r-- | src/relooper/Relooper.cpp | 9 | ||||
-rw-r--r-- | src/runtime.js | 5 | ||||
-rw-r--r-- | src/settings.js | 7 | ||||
-rw-r--r-- | src/shell.html | 2 | ||||
-rw-r--r-- | src/shell.js | 2 | ||||
-rw-r--r-- | src/simd.js | 1031 |
17 files changed, 1343 insertions, 853 deletions
diff --git a/src/compiler.js b/src/compiler.js index aa3c7b92..7d768c3d 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -206,12 +206,12 @@ if (phase == 'pre') { if (VERBOSE) printErr('VERBOSE is on, this generates a lot of output and can slow down compilation'); // Load struct and define information. -try { +//try { var temp = JSON.parse(read(STRUCT_INFO)); -} catch(e) { - printErr('cannot load struct info at ' + STRUCT_INFO + ' : ' + e + ', trying in current dir'); - temp = JSON.parse(read('struct_info.compiled.json')); -} +//} catch(e) { +// printErr('cannot load struct info at ' + STRUCT_INFO + ' : ' + e + ', trying in current dir'); +// temp = JSON.parse(read('struct_info.compiled.json')); +//} C_STRUCTS = temp.structs; C_DEFINES = temp.defines; @@ -224,12 +224,12 @@ load('analyzer.js'); load('jsifier.js'); if (phase == 'funcs' && RELOOP) { // XXX handle !singlePhase RelooperModule = { TOTAL_MEMORY: ceilPowerOfTwo(2*RELOOPER_BUFFER_SIZE) }; - try { + //try { load(RELOOPER); - } catch(e) { - printErr('cannot load relooper at ' + RELOOPER + ' : ' + e + ', trying in current dir'); - load('relooper.js'); - } + //} catch(e) { + // printErr('cannot load relooper at ' + RELOOPER + ' : ' + e + ', trying in current dir'); + // load('relooper.js'); + //} assert(typeof Relooper != 'undefined'); } globalEval(processMacros(preprocess(read('runtime.js')))); @@ -267,7 +267,7 @@ function compile(raw) { function runPhase(currPhase) { //printErr('// JS compiler in action, phase ' + currPhase + typeof lines + (lines === null)); phase = currPhase; - if (phase != 'pre') { + if (phase != 'pre' && phase != 'glue') { if (singlePhase) PassManager.load(read(forwardedDataFile)); if (phase == 'funcs') { @@ -313,14 +313,16 @@ B = new Benchmarker(); try { if (ll_file) { - if (ll_file.indexOf(String.fromCharCode(10)) == -1) { + if (phase === 'glue') { + compile(';'); + } else if (ll_file.indexOf(String.fromCharCode(10)) == -1) { compile(read(ll_file)); } else { compile(ll_file); // we are given raw .ll } } } catch(err) { - printErr('aborting from js compiler due to exception: ' + err); + printErr('aborting from js compiler due to exception: ' + err + ' | ' + err.stack); } //var M = keys(tokenCacheMisses).map(function(m) { return [m, misses[m]] }).sort(function(a, b) { return a[1] - b[1] }); diff --git a/src/intertyper.js b/src/intertyper.js index 940c677f..b34d0c08 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -524,6 +524,27 @@ function intertyper(lines, sidePass, baseLineNums) { } }); } + } else if (ident == '_llvm_used') { + var chunk = item.tokens[1].tokens; + var funcs = []; + var part = []; + + for (var i = 0; i < chunk.length; i++) { + if (chunk[i].text == ',') { + var call = parseLLVMFunctionCall(part); + EXPORTED_FUNCTIONS[call.ident] = 0; + part = []; + } else { + part.push(chunk[i]); + } + } + if (part.length > 0) { + var call = parseLLVMFunctionCall(part); + EXPORTED_FUNCTIONS[call.ident] = 0; + } + + ret.type = 'i32'; + ret.value = { intertype: 'value', ident: '0', value: '0', type: ret.type }; } else if (!external) { if (item.tokens[1] && item.tokens[1].text != ';') { if (item.tokens[1].text == 'c') { @@ -538,6 +559,7 @@ function intertyper(lines, sidePass, baseLineNums) { ret.value = { intertype: 'value', ident: '0', value: '0', type: ret.type }; } } + return ret; } } @@ -616,7 +638,8 @@ function intertyper(lines, sidePass, baseLineNums) { // 'bitcast' function bitcastHandler(item) { item.intertype = 'bitcast'; - item.type = item.tokens[4].text; // The final type + var last = getTokenIndexByText(item.tokens, ';'); + item.type = item.tokens[Math.min(last, item.tokens.length-1)].text; // The final type Types.needAnalysis[item.type] = 0; var to = getTokenIndexByText(item.tokens, 'to'); item.params = [parseLLVMSegment(item.tokens.slice(1, to))]; diff --git a/src/jsifier.js b/src/jsifier.js index acfb6365..907855e7 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -28,7 +28,7 @@ function JSify(data, functionsOnly, givenFunctions) { if (mainPass) { var shellFile = SHELL_FILE ? SHELL_FILE : (BUILD_AS_SHARED_LIB || SIDE_MODULE ? 'shell_sharedlib.js' : 'shell.js'); - if (phase == 'pre') { + if (phase == 'pre' || phase == 'glue') { // We will start to print out the data, but must do so carefully - we are // dealing with potentially *huge* strings. Convenient replacements and // manipulations may create in-memory copies, and we may OOM. @@ -72,7 +72,7 @@ function JSify(data, functionsOnly, givenFunctions) { LibraryManager.load(); //B.stop('jsifier-libload'); - if (phase == 'pre') { + if (phase == 'pre' || phase == 'glue') { var libFuncsToInclude; if (INCLUDE_FULL_LIBRARY) { assert(!(BUILD_AS_SHARED_LIB || SIDE_MODULE), 'Cannot have both INCLUDE_FULL_LIBRARY and BUILD_AS_SHARED_LIB/SIDE_MODULE set.') @@ -474,7 +474,7 @@ function JSify(data, functionsOnly, givenFunctions) { } } if (SIDE_MODULE) return ';'; // we import into the side module js library stuff from the outside parent - if ((!ASM_JS || phase == 'pre') && + if ((!ASM_JS || phase == 'pre' || phase == 'glue') && (EXPORT_ALL || (ident in EXPORTED_FUNCTIONS))) { contentText += '\nModule["' + ident + '"] = ' + ident + ';'; } @@ -1373,8 +1373,9 @@ function JSify(data, functionsOnly, givenFunctions) { function insertelementHandler(item) { var base = getVectorBaseType(item.type); var ident = ensureVector(item.ident, base); + var laneOp = ((base == 'float') ? 'SIMD.float32x4.with' : 'SIMD.int32x4.with'); //return ident + '.with' + SIMDLane[finalizeLLVMParameter(item.index)] + '(' + finalizeLLVMParameter(item.value) + ')'; - return 'SIMD.with' + SIMDLane[finalizeLLVMParameter(item.index)] + '(' + ident + ',' + finalizeLLVMParameter(item.value) + ')'; + return laneOp + SIMDLane[finalizeLLVMParameter(item.index)] + '(' + ident + ',' + finalizeLLVMParameter(item.value) + ')'; } function extractelementHandler(item) { var base = getVectorBaseType(item.type); @@ -1603,6 +1604,15 @@ function JSify(data, functionsOnly, givenFunctions) { } } + // we alias llvm memset and such to normal memset. The target has a return value, while the original + // does not, so we need to fix that for the actual call target + if (ASM_JS) { + var sig = LibraryManager.library[simpleIdent + '__sig']; + if (sig && sig[0] !== 'v') { + returnType = Functions.getSignatureType(sig[0]); + } + } + if (byPointer) { var sig = Functions.getSignature(returnType, argsTypes, hasVarArgs); if (ASM_JS) { @@ -1704,7 +1714,7 @@ function JSify(data, functionsOnly, givenFunctions) { // if (!mainPass) { - if (phase == 'pre' && !Variables.generatedGlobalBase && !BUILD_AS_SHARED_LIB) { + if ((phase == 'pre' || phase == 'glue') && !Variables.generatedGlobalBase && !BUILD_AS_SHARED_LIB) { Variables.generatedGlobalBase = true; // Globals are done, here is the rest of static memory assert((TARGET_LE32 && Runtime.GLOBAL_BASE == 8) || (TARGET_X86 && Runtime.GLOBAL_BASE == 4)); // this is assumed in e.g. relocations for linkable modules @@ -1719,7 +1729,7 @@ function JSify(data, functionsOnly, givenFunctions) { var generated = itemsDict.function.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.GlobalVariable); print(generated.map(function(item) { return item.JS; }).join('\n')); - if (phase == 'pre') { + if (phase == 'pre' || phase == 'glue') { if (memoryInitialization.length > 0) { // apply postsets directly into the big memory initialization itemsDict.GlobalVariablePostSet = itemsDict.GlobalVariablePostSet.filter(function(item) { @@ -1742,15 +1752,17 @@ function JSify(data, functionsOnly, givenFunctions) { }); // write out the singleton big memory initialization value print('/* memory initializer */ ' + makePointer(memoryInitialization, null, 'ALLOC_NONE', 'i8', 'Runtime.GLOBAL_BASE' + (SIDE_MODULE ? '+H_BASE' : ''), true)); - } else { + } else if (phase !== 'glue') { print('/* no memory initializer */'); // test purposes } - // Define postsets. These will be run in ATINIT, right before global initializers (which might need the postsets). We cannot - // run them now because the memory initializer might not have been applied yet. - print('function runPostSets() {\n'); - print(itemsDict.GlobalVariablePostSet.map(function(item) { return item.JS }).join('\n')); - print('}\n'); + if (phase !== 'glue') { + // Define postsets. These will be run in ATINIT, right before global initializers (which might need the postsets). We cannot + // run them now because the memory initializer might not have been applied yet. + print('function runPostSets() {\n'); + print(itemsDict.GlobalVariablePostSet.map(function(item) { return item.JS }).join('\n')); + print('}\n'); + } if (USE_TYPED_ARRAYS == 2) { if (!BUILD_AS_SHARED_LIB && !SIDE_MODULE) { @@ -1780,7 +1792,7 @@ function JSify(data, functionsOnly, givenFunctions) { } // Print out global variables and postsets TODO: batching - if (phase == 'pre') { + if (phase == 'pre' || phase == 'glue') { var legalizedI64sDefault = legalizedI64s; legalizedI64s = false; diff --git a/src/library.js b/src/library.js index a5380c3a..26d766e9 100644 --- a/src/library.js +++ b/src/library.js @@ -23,6 +23,7 @@ LibraryManager.library = { stdout: 'allocate(1, "i32*", ALLOC_STATIC)', stderr: 'allocate(1, "i32*", ALLOC_STATIC)', _impure_ptr: 'allocate(1, "i32*", ALLOC_STATIC)', + __dso_handle: 'allocate(1, "i32*", ALLOC_STATIC)', // ========================================================================== // dirent.h @@ -471,6 +472,11 @@ LibraryManager.library = { mkstemp: function(template) { return _creat(_mktemp(template), 0600); }, + mkdtemp__deps: ['mktemp', 'mkdir'], + mkdtemp: function(template) { + template = _mktemp(template); + return (_mkdir(template, 0700) === 0) ? template : 0; + }, fcntl__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], fcntl: function(fildes, cmd, varargs, dup2) { // int fcntl(int fildes, int cmd, ...); @@ -535,7 +541,7 @@ LibraryManager.library = { // Advise as much as you wish. We don't care. return 0; }, - posix_madvise: 'posix_fadvise', + posix_madvise: function(){ return 0 }, // ditto as fadvise posix_fallocate__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], posix_fallocate: function(fd, offset, len) { // int posix_fallocate(int fd, off_t offset, off_t len); @@ -1855,7 +1861,11 @@ LibraryManager.library = { // int x = 4; printf("%c\n", (char)x); var ret; if (type === 'double') { +#if TARGET_LE32 == 2 + ret = {{{ makeGetValue('varargs', 'argIndex', 'double', undefined, undefined, true, 4) }}}; +#else ret = {{{ makeGetValue('varargs', 'argIndex', 'double', undefined, undefined, true) }}}; +#endif #if USE_TYPED_ARRAYS == 2 } else if (type == 'i64') { @@ -1876,7 +1886,11 @@ LibraryManager.library = { type = 'i32'; // varargs are always i32, i64, or double ret = {{{ makeGetValue('varargs', 'argIndex', 'i32', undefined, undefined, true) }}}; } +#if TARGET_LE32 == 2 + argIndex += Runtime.getNativeFieldSize(type); +#else argIndex += Math.max(Runtime.getNativeFieldSize(type), Runtime.getAlignSize(type, null, true)); +#endif return ret; } @@ -2505,6 +2519,10 @@ LibraryManager.library = { } var bytesRead = 0; var streamObj = FS.getStream(stream); + if (!streamObj) { + ___setErrNo(ERRNO_CODES.EBADF); + return 0; + } while (streamObj.ungotten.length && bytesToRead > 0) { {{{ makeSetValue('ptr++', '0', 'streamObj.ungotten.pop()', 'i8') }}} bytesToRead--; @@ -3522,13 +3540,15 @@ LibraryManager.library = { llvm_memcpy_p0i8_p0i8_i32: 'memcpy', llvm_memcpy_p0i8_p0i8_i64: 'memcpy', - memmove__sig: 'viii', + memmove__sig: 'iiii', memmove__asm: true, memmove__deps: ['memcpy'], memmove: function(dest, src, num) { dest = dest|0; src = src|0; num = num|0; + var ret = 0; if (((src|0) < (dest|0)) & ((dest|0) < ((src + num)|0))) { // Unlikely case: Copy backwards in a safe manner + ret = dest; src = (src + num)|0; dest = (dest + num)|0; while ((num|0) > 0) { @@ -3537,9 +3557,11 @@ LibraryManager.library = { num = (num - 1)|0; {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}}; } + dest = ret; } else { _memcpy(dest, src, num) | 0; } + return dest | 0; }, llvm_memmove_i32: 'memmove', llvm_memmove_i64: 'memmove', @@ -3556,7 +3578,7 @@ LibraryManager.library = { memset__inline: function(ptr, value, num, align) { return makeSetValues(ptr, 0, value, 'null', num, align); }, - memset__sig: 'viii', + memset__sig: 'iiii', memset__asm: true, memset: function(ptr, value, num) { #if USE_TYPED_ARRAYS == 2 @@ -3585,8 +3607,10 @@ LibraryManager.library = { {{{ makeSetValueAsm('ptr', 0, 'value', 'i8') }}}; ptr = (ptr+1)|0; } + return (ptr-num)|0; #else {{{ makeSetValues('ptr', '0', 'value', 'null', 'num') }}}; + return ptr; #endif }, llvm_memset_i32: 'memset', @@ -4657,6 +4681,10 @@ LibraryManager.library = { llvm_dbg_declare__inline: function() { throw 'llvm_debug_declare' }, // avoid warning + // llvm-nacl + + llvm_nacl_atomic_store_i32__inline: true, + // ========================================================================== // llvm-mono integration // ========================================================================== @@ -6955,7 +6983,7 @@ LibraryManager.library = { pthread_setspecific__deps: ['$PTHREAD_SPECIFIC', '$ERRNO_CODES'], pthread_setspecific: function(key, value) { - if (value == 0) { + if (!(key in PTHREAD_SPECIFIC)) { return ERRNO_CODES.EINVAL; } PTHREAD_SPECIFIC[key] = value; @@ -8724,8 +8752,72 @@ LibraryManager.library = { // emscripten vector ops //============================ - emscripten_float32x4_signmask__inline: function(x) { - return x + '.signMask()'; + emscripten_float32x4_signmask__inline: function(a) { + return 'SIMD.float32x4.bitsToInt32x4(' + a + ').signMask'; + }, + + emscripten_float32x4_min__inline: function(a, b) { + return 'SIMD.float32x4.min(' + a + ', ' + b + ')'; + }, + + emscripten_float32x4_max__inline: function(a, b) { + return 'SIMD.float32x4.max(' + a + ', ' + b + ')'; + }, + + emscripten_float32x4_sqrt__inline: function(a) { + return 'SIMD.float32x4.sqrt(' + a + ')'; + }, + + emscripten_float32x4_lessThan__inline: function(a, b) { + return 'SIMD.int32x4.bitsToFloat32x4(SIMD.float32x4.lessThan(' + a + ', ' + b + '))'; + }, + + emscripten_float32x4_lessThanOrEqual__inline: function(a, b) { + return 'SIMD.int32x4.bitsToFloat32x4(SIMD.float32x4.lessThanOrEqual(' + a + ', ' + b + '))'; + }, + + emscripten_float32x4_equal__inline: function(a, b) { + return 'SIMD.int32x4.bitsToFloat32x4(SIMD.float32x4.equal(' + a + ', ' + b + '))'; + }, + + emscripten_float32x4_greaterThanOrEqual__inline: function(a, b) { + return 'SIMD.int32x4.bitsToFloat32x4(SIMD.float32x4.greaterThanOrEqual(' + a + ', ' + b + '))'; + }, + + emscripten_float32x4_greaterThan__inline: function(a, b) { + return 'SIMD.int32x4.bitsToFloat32x4(SIMD.float32x4.greaterThan(' + a + ', ' + b + '))'; + }, + + emscripten_float32x4_and__inline: function(a, b) { + return 'SIMD.int32x4.bitsToFloat32x4(SIMD.int32x4.and(SIMD.float32x4.bitsToInt32x4(' + a + '), SIMD.float32x4.bitsToInt32x4(' + b + ')))'; + }, + + emscripten_float32x4_andNot__inline: function(a, b) { + return 'SIMD.int32x4.bitsToFloat32x4(SIMD.int32x4.and(SIMD.int32x4.not(SIMD.float32x4.bitsToInt32x4(' + a + ')), SIMD.float32x4.bitsToInt32x4(' + b + ')))'; + }, + + emscripten_float32x4_or__inline: function(a, b) { + return 'SIMD.int32x4.bitsToFloat32x4(SIMD.int32x4.or(SIMD.float32x4.bitsToInt32x4(' + a + '), SIMD.float32x4.bitsToInt32x4(' + b + ')))'; + }, + + emscripten_float32x4_xor__inline: function(a, b) { + return 'SIMD.int32x4.bitsToFloat32x4(SIMD.int32x4.xor(SIMD.float32x4.bitsToInt32x4(' + a + '), SIMD.float32x4.bitsToInt32x4(' + b + ')))'; + }, + + emscripten_int32x4_bitsToFloat32x4__inline: function(a) { + return 'SIMD.int32x4.bitsToFloat32x4(' + a + ')'; + }, + + emscripten_int32x4_toFloat32x4__inline: function(a) { + return 'SIMD.int32x4.toFloat32x4(' + a + ')'; + }, + + emscripten_float32x4_bitsToInt32x4__inline: function(a) { + return 'SIMD.float32x4.bitsToInt32x4(' + a + ')'; + }, + + emscripten_float32x4_toInt32x4__inline: function(a) { + return 'SIMD.float32x4.toInt32x4(' + a + ')'; }, //============================ diff --git a/src/library_browser.js b/src/library_browser.js index 8444fb73..b368c6ac 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -250,15 +250,24 @@ mergeInto(LibraryManager.library, { contextAttributes.preserveDrawingBuffer = true; #endif - ['experimental-webgl', 'webgl'].some(function(webglId) { - return ctx = canvas.getContext(webglId, contextAttributes); - }); + var errorInfo = '?'; + function onContextCreationError(event) { + errorInfo = event.statusMessage || errorInfo; + } + canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false); + try { + ['experimental-webgl', 'webgl'].some(function(webglId) { + return ctx = canvas.getContext(webglId, contextAttributes); + }); + } finally { + canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false); + } } else { ctx = canvas.getContext('2d'); } if (!ctx) throw ':('; } catch (e) { - Module.print('Could not create canvas - ' + e); + Module.print('Could not create canvas: ' + [errorInfo, e]); return null; } if (useWebGL) { @@ -854,7 +863,7 @@ mergeInto(LibraryManager.library, { var styleSheet = document.styleSheets[0]; var rules = styleSheet.cssRules; for (var i = 0; i < rules.length; i++) { - if (rules[i].cssText.substr(0, 5) == 'canvas') { + if (rules[i].cssText.substr(0, 6) == 'canvas') { styleSheet.deleteRule(i); i--; } diff --git a/src/library_gl.js b/src/library_gl.js index afd36197..cc39b048 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -209,6 +209,105 @@ var LibraryGL = { ((height - 1) * alignedRowSize + plainRowSize); }, + get: function(name_, p, type) { + var ret = undefined; + switch(name_) { // Handle a few trivial GLES values + case 0x8DFA: // GL_SHADER_COMPILER + ret = 1; + break; + case 0x8DF8: // GL_SHADER_BINARY_FORMATS + if (type === 'Integer') { + // fall through, see gles2_conformance.cpp + } else { + GL.recordError(0x0500); // GL_INVALID_ENUM +#if GL_ASSERTIONS + Module.printErr('GL_INVALID_ENUM in glGet' + type + 'v(GL_SHADER_BINARY_FORMATS): Invalid parameter type!'); +#endif + return; + } + case 0x8DF9: // GL_NUM_SHADER_BINARY_FORMATS + ret = 0; + break; + case 0x86A2: // GL_NUM_COMPRESSED_TEXTURE_FORMATS + // WebGL doesn't have GL_NUM_COMPRESSED_TEXTURE_FORMATS (it's obsolete since GL_COMPRESSED_TEXTURE_FORMATS returns a JS array that can be queried for length), + // so implement it ourselves to allow C++ GLES2 code get the length. + var formats = Module.ctx.getParameter(0x86A3 /*GL_COMPRESSED_TEXTURE_FORMATS*/); + ret = formats.length; + break; + case 0x8B9A: // GL_IMPLEMENTATION_COLOR_READ_TYPE + ret = 0x1401; // GL_UNSIGNED_BYTE + break; + case 0x8B9B: // GL_IMPLEMENTATION_COLOR_READ_FORMAT + ret = 0x1908; // GL_RGBA + break; + } + + if (ret === undefined) { + var result = Module.ctx.getParameter(name_); + switch (typeof(result)) { + case "number": + ret = result; + break; + case "boolean": + ret = result ? 1 : 0; + break; + case "string": + GL.recordError(0x0500); // GL_INVALID_ENUM +#if GL_ASSERTIONS + Module.printErr('GL_INVALID_ENUM in glGet' + type + 'v(' + name_ + ') on a name which returns a string!'); +#endif + return; + case "object": + if (result === null) { + GL.recordError(0x0500); // GL_INVALID_ENUM +#if GL_ASSERTIONS + Module.printErr('GL_INVALID_ENUM in glGet' + type + 'v(' + name_ + ') and it returns null!'); +#endif + return; + } else if (result instanceof Float32Array || + result instanceof Uint32Array || + result instanceof Int32Array || + result instanceof Array) { + for (var i = 0; i < result.length; ++i) { + switch (type) { + case 'Integer': {{{ makeSetValue('p', 'i*4', 'result[i]', 'i32') }}}; break; + case 'Float': {{{ makeSetValue('p', 'i*4', 'result[i]', 'float') }}}; break; + case 'Boolean': {{{ makeSetValue('p', 'i', 'result[i] ? 1 : 0', 'i8') }}}; break; + default: throw 'internal glGet error, bad type: ' + type; + } + } + return; + } else if (result instanceof WebGLBuffer || + result instanceof WebGLProgram || + result instanceof WebGLFramebuffer || + result instanceof WebGLRenderbuffer || + result instanceof WebGLTexture) { + ret = result.name | 0; + } else { + GL.recordError(0x0500); // GL_INVALID_ENUM +#if GL_ASSERTIONS + Module.printErr('GL_INVALID_ENUM in glGet' + type + 'v: Unknown object returned from WebGL getParameter(' + name_ + ')!'); +#endif + return; + } + break; + default: + GL.recordError(0x0500); // GL_INVALID_ENUM +#if GL_ASSERTIONS + Module.printErr('GL_INVALID_ENUM in glGetIntegerv: Native code calling glGet' + type + 'v(' + name_ + ') and it returns ' + result + ' of type ' + typeof(result) + '!'); +#endif + return; + } + } + + switch (type) { + case 'Integer': {{{ makeSetValue('p', '0', 'ret', 'i32') }}}; break; + case 'Float': {{{ makeSetValue('p', '0', 'ret', 'float') }}}; break; + case 'Boolean': {{{ makeSetValue('p', '0', 'ret ? 1 : 0', 'i8') }}}; break; + default: throw 'internal glGet error, bad type: ' + type; + } + }, + getTexPixelData: function(type, format, width, height, pixels, internalFormat) { var sizePerPixel; switch (type) { @@ -288,6 +387,22 @@ var LibraryGL = { } }, +#if GL_FFP_ONLY + enabledClientAttribIndices: [], + enableVertexAttribArray: function enableVertexAttribArray(index) { + if (!GL.enabledClientAttribIndices[index]) { + GL.enabledClientAttribIndices[index] = true; + Module.ctx.enableVertexAttribArray(index); + } + }, + disableVertexAttribArray: function disableVertexAttribArray(index) { + if (GL.enabledClientAttribIndices[index]) { + GL.enabledClientAttribIndices[index] = false; + Module.ctx.disableVertexAttribArray(index); + } + }, +#endif + #if FULL_ES2 calcBufLength: function calcBufLength(size, type, stride, count) { if (stride > 0) { @@ -554,214 +669,17 @@ var LibraryGL = { glGetIntegerv__sig: 'vii', glGetIntegerv: function(name_, p) { - switch(name_) { // Handle a few trivial GLES values - case 0x8DFA: // GL_SHADER_COMPILER - {{{ makeSetValue('p', '0', '1', 'i32') }}}; - return; - case 0x8DF8: // GL_SHADER_BINARY_FORMATS - case 0x8DF9: // GL_NUM_SHADER_BINARY_FORMATS - {{{ makeSetValue('p', '0', '0', 'i32') }}}; - return; - case 0x86A2: // GL_NUM_COMPRESSED_TEXTURE_FORMATS - // WebGL doesn't have GL_NUM_COMPRESSED_TEXTURE_FORMATS (it's obsolete since GL_COMPRESSED_TEXTURE_FORMATS returns a JS array that can be queried for length), - // so implement it ourselves to allow C++ GLES2 code get the length. - var formats = Module.ctx.getParameter(0x86A3 /*GL_COMPRESSED_TEXTURE_FORMATS*/); - {{{ makeSetValue('p', '0', 'formats.length', 'i32') }}}; - return; - } - var result = Module.ctx.getParameter(name_); - switch (typeof(result)) { - case "number": - {{{ makeSetValue('p', '0', 'result', 'i32') }}}; - break; - case "boolean": - {{{ makeSetValue('p', '0', 'result ? 1 : 0', 'i8') }}}; - break; - case "string": - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetIntegerv: Native code calling glGetIntegerv(' + name_ + ') on a name which returns a string!'); -#endif - return; - case "object": - if (result === null) { - {{{ makeSetValue('p', '0', '0', 'i32') }}}; - } else if (result instanceof Float32Array || - result instanceof Uint32Array || - result instanceof Int32Array || - result instanceof Array) { - for (var i = 0; i < result.length; ++i) { - {{{ makeSetValue('p', 'i*4', 'result[i]', 'i32') }}}; - } - } else if (result instanceof WebGLBuffer) { - {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}}; - } else if (result instanceof WebGLProgram) { - {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}}; - } else if (result instanceof WebGLFramebuffer) { - {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}}; - } else if (result instanceof WebGLRenderbuffer) { - {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}}; - } else if (result instanceof WebGLTexture) { - {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}}; - } else { - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetIntegerv: Unknown object returned from WebGL getParameter(' + name_ + ')!'); -#endif - return; - } - break; - default: - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetIntegerv: Native code calling glGetIntegerv(' + name_ + ') and it returns ' + result + ' of type ' + typeof(result) + '!'); -#endif - return; - } + return GL.get(name_, p, 'Integer'); }, glGetFloatv__sig: 'vii', glGetFloatv: function(name_, p) { - switch(name_) { - case 0x8DFA: // GL_SHADER_COMPILER - {{{ makeSetValue('p', '0', '1', 'float') }}}; - return; - case 0x8DF8: // GL_SHADER_BINARY_FORMATS - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetFloatv(GL_SHADER_BINARY_FORMATS): Invalid parameter type!'); -#endif - return; - case 0x8DF9: // GL_NUM_SHADER_BINARY_FORMATS - {{{ makeSetValue('p', '0', '0', 'float') }}}; - return; - case 0x86A2: // GL_NUM_COMPRESSED_TEXTURE_FORMATS - // WebGL doesn't have GL_NUM_COMPRESSED_TEXTURE_FORMATS (it's obsolete since GL_COMPRESSED_TEXTURE_FORMATS returns a JS array that can be queried for length), - // so implement it ourselves to allow C++ GLES2 code get the length. - var formats = Module.ctx.getParameter(0x86A3 /*GL_COMPRESSED_TEXTURE_FORMATS*/); - {{{ makeSetValue('p', '0', 'formats.length', 'float') }}}; - return; - } - - var result = Module.ctx.getParameter(name_); - switch (typeof(result)) { - case "number": - {{{ makeSetValue('p', '0', 'result', 'float') }}}; - break; - case "boolean": - {{{ makeSetValue('p', '0', 'result ? 1.0 : 0.0', 'float') }}}; - break; - case "string": - {{{ makeSetValue('p', '0', '0', 'float') }}}; - case "object": - if (result === null) { - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetFloatv: Native code calling glGetFloatv(' + name_ + ') and it returns null!'); -#endif - return; - } else if (result instanceof Float32Array || - result instanceof Uint32Array || - result instanceof Int32Array || - result instanceof Array) { - for (var i = 0; i < result.length; ++i) { - {{{ makeSetValue('p', 'i*4', 'result[i]', 'float') }}}; - } - } else if (result instanceof WebGLBuffer) { - {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}}; - } else if (result instanceof WebGLProgram) { - {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}}; - } else if (result instanceof WebGLFramebuffer) { - {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}}; - } else if (result instanceof WebGLRenderbuffer) { - {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}}; - } else if (result instanceof WebGLTexture) { - {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}}; - } else { - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetFloatv: Native code calling glGetFloatv(' + name_ + ') and it returns ' + result + ' of type ' + typeof(result) + '!'); -#endif - return; - } - break; - default: - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetFloatv: Native code calling glGetFloatv(' + name_ + ') and it returns ' + result + ' of type ' + typeof(result) + '!'); -#endif - return; - } + return GL.get(name_, p, 'Float'); }, glGetBooleanv__sig: 'vii', glGetBooleanv: function(name_, p) { - switch(name_) { - case 0x8DFA: // GL_SHADER_COMPILER - {{{ makeSetValue('p', '0', '1', 'i8') }}}; - return; - case 0x8DF8: // GL_SHADER_BINARY_FORMATS - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetBooleanv(GL_SHADER_BINARY_FORMATS): Invalid parameter type!'); -#endif - return; - case 0x8DF9: // GL_NUM_SHADER_BINARY_FORMATS - {{{ makeSetValue('p', '0', '0', 'i8') }}}; - return; - case 0x86A2: // GL_NUM_COMPRESSED_TEXTURE_FORMATS - // WebGL doesn't have GL_NUM_COMPRESSED_TEXTURE_FORMATS (it's obsolete since GL_COMPRESSED_TEXTURE_FORMATS returns a JS array that can be queried for length), - // so implement it ourselves to allow C++ GLES2 code get the length. - var hasCompressedFormats = Module.ctx.getParameter(0x86A3 /*GL_COMPRESSED_TEXTURE_FORMATS*/).length > 0 ? 1 : 0; - {{{ makeSetValue('p', '0', 'hasCompressedFormats', 'i8') }}}; - return; - } - - var result = Module.ctx.getParameter(name_); - switch (typeof(result)) { - case "number": - {{{ makeSetValue('p', '0', 'result != 0', 'i8') }}}; - break; - case "boolean": - {{{ makeSetValue('p', '0', 'result != 0', 'i8') }}}; - break; - case "string": - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetBooleanv: Native code calling glGetBooleanv(' + name_ + ') on a name which returns a string!'); -#endif - return; - case "object": - if (result === null) { - {{{ makeSetValue('p', '0', '0', 'i8') }}}; - } else if (result instanceof Float32Array || - result instanceof Uint32Array || - result instanceof Int32Array || - result instanceof Array) { - for (var i = 0; i < result.length; ++i) { - {{{ makeSetValue('p', 'i', 'result[i] != 0', 'i8') }}}; - } - } else if (result instanceof WebGLBuffer || - result instanceof WebGLProgram || - result instanceof WebGLFramebuffer || - result instanceof WebGLRenderbuffer || - result instanceof WebGLTexture) { - {{{ makeSetValue('p', '0', '1', 'i8') }}}; // non-zero ID is always 1! - } else { - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetBooleanv: Unknown object returned from WebGL getParameter(' + name_ + ')!'); -#endif - return; - } - break; - default: - GL.recordError(0x0500/*GL_INVALID_ENUM*/); -#if GL_ASSERTIONS - Module.printErr('GL_INVALID_ENUM in glGetBooleanv: Native code calling glGetBooleanv(' + name_ + ') and it returns ' + result + ' of type ' + typeof(result) + '!'); -#endif - return; - } + return GL.get(name_, p, 'Boolean'); }, glGenTextures__sig: 'vii', @@ - |