aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-12-07 10:37:25 -0500
committerAlon Zakai <alonzakai@gmail.com>2013-12-07 10:37:25 -0500
commit1a007b1631509b9d72499a8f4402294017ee04dc (patch)
tree92f8b0341497c7bd4e53aa82c690346536a244c3 /src
parentdf11c6f1fd1636a355b83a1c48b3a890596e6a32 (diff)
parenteb083723747a90cb6ab9853fec8d6e8ef54748bc (diff)
Merge branch 'incoming'
Diffstat (limited to 'src')
-rw-r--r--src/compiler.js28
-rw-r--r--src/intertyper.js25
-rw-r--r--src/jsifier.js38
-rw-r--r--src/library.js104
-rw-r--r--src/library_browser.js19
-rw-r--r--src/library_gl.js837
-rw-r--r--src/library_sdl.js29
-rw-r--r--src/library_sockfs.js2
-rw-r--r--src/modules.js6
-rw-r--r--src/parseTools.js34
-rw-r--r--src/preamble.js18
-rw-r--r--src/relooper/Relooper.cpp9
-rw-r--r--src/runtime.js5
-rw-r--r--src/settings.js7
-rw-r--r--src/shell.html2
-rw-r--r--src/shell.js2
-rw-r--r--src/simd.js1031
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) {