aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/jsifier.js21
-rw-r--r--src/library.js75
-rw-r--r--src/library_gl.js427
-rw-r--r--src/library_sdl.js80
-rw-r--r--src/long.js1633
-rw-r--r--src/parseTools.js58
-rw-r--r--src/preamble.js22
-rw-r--r--src/settings.js6
8 files changed, 2220 insertions, 102 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index 99176fd2..dcc853f2 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -38,6 +38,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var preFile = BUILD_AS_SHARED_LIB ? 'preamble_sharedlib.js' : 'preamble.js';
var pre = processMacros(preprocess(read(preFile).replace('{{RUNTIME}}', getRuntime())));
print(pre);
+ if (PRECISE_I64_MATH) print(read('long.js'));
Functions.implementedFunctions = set(data.unparsedFunctions.map(function(func) { return func.ident }));
}
@@ -166,23 +167,27 @@ function JSify(data, functionsOnly, givenFunctions) {
ret[index++] = 0;
}
// Add current value(s)
- var currValue = flatten(values[i]);
+ var currValue = values[i];
if (USE_TYPED_ARRAYS == 2 && typeData.fields[i] == 'i64') {
// 'flatten' out the 64-bit value into two 32-bit halves
- ret[index++] = currValue>>>0;
+ var parts = parseI64Constant(currValue, true);
+ ret[index++] = parts[0];
ret[index++] = 0;
ret[index++] = 0;
ret[index++] = 0;
- ret[index++] = Math.floor(currValue/4294967296);
+ ret[index++] = parts[1];
ret[index++] = 0;
ret[index++] = 0;
ret[index++] = 0;
- } else if (typeof currValue == 'object') {
- for (var j = 0; j < currValue.length; j++) {
- ret[index++] = currValue[j];
- }
} else {
- ret[index++] = currValue;
+ currValue = flatten(currValue);
+ if (typeof currValue == 'object') {
+ for (var j = 0; j < currValue.length; j++) {
+ ret[index++] = currValue[j];
+ }
+ } else {
+ ret[index++] = currValue;
+ }
}
i += 1;
}
diff --git a/src/library.js b/src/library.js
index 0574bb8d..f49a8a58 100644
--- a/src/library.js
+++ b/src/library.js
@@ -86,6 +86,23 @@ LibraryManager.library = {
parentPath: null,
parentObject: null
};
+#if FS_LOG
+ var inputPath = path;
+ function log() {
+ print('FS.analyzePath("' + inputPath + '", ' +
+ dontResolveLastLink + ', ' +
+ linksVisited + ') => {' +
+ 'isRoot: ' + ret.isRoot + ', ' +
+ 'exists: ' + ret.exists + ', ' +
+ 'error: ' + ret.error + ', ' +
+ 'name: "' + ret.name + '", ' +
+ 'path: "' + ret.path + '", ' +
+ 'object: ' + ret.object + ', ' +
+ 'parentExists: ' + ret.parentExists + ', ' +
+ 'parentPath: "' + ret.parentPath + '", ' +
+ 'parentObject: ' + ret.parentObject + '}');
+ }
+#endif
path = FS.absolutePath(path);
if (path == '/') {
ret.isRoot = true;
@@ -123,8 +140,12 @@ LibraryManager.library = {
break;
}
var link = FS.absolutePath(current.link, traversed.join('/'));
- return FS.analyzePath([link].concat(path).join('/'),
- dontResolveLastLink, linksVisited + 1);
+ ret = FS.analyzePath([link].concat(path).join('/'),
+ dontResolveLastLink, linksVisited + 1);
+#if FS_LOG
+ log();
+#endif
+ return ret;
}
traversed.push(target);
if (path.length == 0) {
@@ -133,8 +154,10 @@ LibraryManager.library = {
ret.object = current;
}
}
- return ret;
}
+#if FS_LOG
+ log();
+#endif
return ret;
},
// Finds the file system object at a given path. If dontResolveLastLink is
@@ -152,6 +175,13 @@ LibraryManager.library = {
},
// Creates a file system record: file, link, device or folder.
createObject: function(parent, name, properties, canRead, canWrite) {
+#if FS_LOG
+ print('FS.createObject("' + parent + '", ' +
+ '"' + name + '", ' +
+ JSON.stringify(properties) + ', ' +
+ canRead + ', ' +
+ canWrite + ')');
+#endif
if (!parent) parent = '/';
if (typeof parent === 'string') parent = FS.findObject(parent);
@@ -415,6 +445,14 @@ LibraryManager.library = {
standardizePath: function(path) {
if (path.substr(0, 2) == './') path = path.substr(2);
return path;
+ },
+
+ deleteFile: function(path) {
+ var path = FS.analyzePath(path);
+ if (!path.parentExists || !path.exists) {
+ throw 'Invalid path ' + path;
+ }
+ delete path.parentObject.contents[path.name];
}
},
@@ -2449,6 +2487,10 @@ LibraryManager.library = {
var signed = next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0);
argSize = argSize || 4;
var currArg = getNextArg('i' + (argSize * 8));
+#if PRECISE_I64_MATH == 1
+ var origArg = currArg;
+#endif
+ var argText;
#if USE_TYPED_ARRAYS == 2
// Flatten i64-1 [low, high] into a (slightly rounded) double
if (argSize == 8) {
@@ -2462,11 +2504,16 @@ LibraryManager.library = {
}
// Format the number.
var currAbsArg = Math.abs(currArg);
- var argText;
var prefix = '';
if (next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0)) {
+#if PRECISE_I64_MATH == 1
+ if (argSize == 8) argText = i64Math.stringify(origArg[0], origArg[1]); else
+#endif
argText = reSign(currArg, 8 * argSize, 1).toString(10);
} else if (next == 'u'.charCodeAt(0)) {
+#if PRECISE_I64_MATH == 1
+ if (argSize == 8) argText = i64Math.stringify(origArg[0], origArg[1], true); else
+#endif
argText = unSign(currArg, 8 * argSize, 1).toString(10);
currArg = Math.abs(currArg);
} else if (next == 'o'.charCodeAt(0)) {
@@ -4209,11 +4256,19 @@ LibraryManager.library = {
isdigit: function(chr) {
return chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0);
},
+ isdigit_l__deps: ['isdigit'],
+ isdigit_l: function(chr, loc) {
+ return _isdigit(chr);
+ },
isxdigit: function(chr) {
return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) ||
(chr >= 'a'.charCodeAt(0) && chr <= 'f'.charCodeAt(0)) ||
(chr >= 'A'.charCodeAt(0) && chr <= 'F'.charCodeAt(0));
},
+ isxdigit_l__deps: ['isxdigit'],
+ isxdigit_l: function(chr, loc) {
+ return _isxdigit(chr);
+ },
isalnum: function(chr) {
return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) ||
(chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) ||
@@ -4604,16 +4659,20 @@ LibraryManager.library = {
_ZTIPv: [0],
llvm_uadd_with_overflow_i32: function(x, y) {
+ x = x>>>0;
+ y = y>>>0;
return {
- f0: x+y,
- f1: 0 // We never overflow... for now
+ f0: (x+y)>>>0,
+ f1: x+y > 4294967295
};
},
llvm_umul_with_overflow_i32: function(x, y) {
+ x = x>>>0;
+ y = y>>>0;
return {
- f0: x*y,
- f1: 0 // We never overflow... for now
+ f0: (x*y)>>>0,
+ f1: x*y > 4294967295
};
},
diff --git a/src/library_gl.js b/src/library_gl.js
index 91f7d353..99c0f2f1 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -1,6 +1,15 @@
//"use strict";
-// XXX FIXME Hardcoded '4' in many places, here and in library_SDL, for RGBA
+// FIXME:
+// * glGetUniformLocation should return -1 when the value is not valid, not null
+// * glUniform1fi should be glUniform1iv
+// * glGetAttribLocation lacks return value (and should be -1 when not valid)
+// * single-underscore deps need double underscore (and, just auto-add them all)
+// * glGetProgramInfoLog and *shader* should be essentially identical
+// * glGetIntegerv set to bool etc needs fixing
+// * glVertexAttribPointer - the last param can be an offset or in gles, a raw pointer to clientside data. need some way to
+// warn about that since it silently fails in WebGL (it's a huge offset into the last bound buffer, zeros)
+
var LibraryGL = {
$GL: {
@@ -24,6 +33,14 @@ var LibraryGL = {
#endif
return this.table[id];
},
+ id: function(obj) {
+ for (var i = 1; i < this.counter; ++i) {
+ if (obj == this.table[i]) {
+ return i;
+ }
+ }
+ return null;
+ },
remove: function(id) {
if( id == 0 ) return;
#if ASSERTIONS
@@ -45,11 +62,11 @@ var LibraryGL = {
glGetString: function(name_) {
switch(name_) {
- case Module.ctx.VENDOR:
- case Module.ctx.RENDERER:
- case Module.ctx.VERSION:
+ case 0x1F00 /* GL_VENDOR */:
+ case 0x1F01 /* GL_RENDERER */:
+ case 0x1F02 /* GL_VERSION */:
return allocate(intArrayFromString(Module.ctx.getParameter(name_)), 'i8', ALLOC_NORMAL);
- case 0x1F03: // Extensions
+ case 0x1F03 /* GL_EXTENSIONS */:
return allocate(intArrayFromString(Module.ctx.getSupportedExtensions().join(' ')), 'i8', ALLOC_NORMAL);
default:
throw 'Failure: Invalid glGetString value: ' + name_;
@@ -58,17 +75,125 @@ var LibraryGL = {
glGenIntegerv__deps: ['$GL'],
glGetIntegerv: function(name_, p) {
- var v = Module.ctx.getParameter(name_);
- if (name_ == Module.ctx.CURRENT_PROGRAM)
- v = GL.hashtable("program").lookup(v);
- else if (name_ == Module.ctx.VIEWPORT) {
- {{{ makeSetValue('p', '0', 'v[0]', 'i32') }}};
- {{{ makeSetValue('p', '4', 'v[1]', 'i32') }}};
- {{{ makeSetValue('p', '8', 'v[2]', 'i32') }}};
- {{{ makeSetValue('p', '12', 'v[3]', 'i32') }}};
+ 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', 'i32') }}};
+ break;
+ case "string":
+ throw 'Native code calling glGetIntegerv(' + name_ + ') on a name which returns a string!';
+ 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', 'result[i]', 'i32') }}};
+ }
+ } else if (result instanceof WebGLBuffer) {
+ {{{ makeSetValue('p', '0', 'GL.hashtable("buffer").id(result)', 'i32') }}};
+ } else if (result instanceof WebGLProgram) {
+ {{{ makeSetValue('p', '0', 'GL.hashtable("program").id(result)', 'i32') }}};
+ } else if (result instanceof WebGLFramebuffer) {
+ {{{ makeSetValue('p', '0', 'GL.hashtable("framebuffer").id(result)', 'i32') }}};
+ } else if (result instanceof WebGLRenderbuffer) {
+ {{{ makeSetValue('p', '0', 'gl.hashtable("renderbuffer").id(result)', 'i32') }}};
+ } else if (result instanceof WebGLTexture) {
+ {{{ makeSetValue('p', '0', 'gl.hashtable("texture").id(result)', 'i32') }}};
+ } else {
+ throw 'Unknown object returned from WebGL getParameter';
+ }
+ break;
+ case "undefined":
+ throw 'Native code calling glGetIntegerv(' + name_ + ') and it returns undefined';
+ default:
+ throw 'Why did we hit the default case?';
+ }
+ },
+
+ glGetFloatv: function(name_, p) {
+ 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) {
+ throw 'Native code calling glGetFloatv(' + name_ + ') and it returns null';
+ } 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]', 'float') }}};
+ }
+ } else if (result instanceof WebGLBuffer) {
+ {{{ makeSetValue('p', '0', 'GL.hashtable("buffer").id(result)', 'float') }}};
+ } else if (result instanceof WebGLProgram) {
+ {{{ makeSetValue('p', '0', 'GL.hashtable("program").id(result)', 'float') }}};
+ } else if (result instanceof WebGLFramebuffer) {
+ {{{ makeSetValue('p', '0', 'GL.hashtable("framebuffer").id(result)', 'float') }}};
+ } else if (result instanceof WebGLRenderbuffer) {
+ {{{ makeSetValue('p', '0', 'gl.hashtable("renderbuffer").id(result)', 'float') }}};
+ } else if (result instanceof WebGLTexture) {
+ {{{ makeSetValue('p', '0', 'gl.hashtable("texture").id(result)', 'float') }}};
+ } else {
+ throw 'Unknown object returned from WebGL getParameter';
+ }
+ break;
+ case "undefined":
+ throw 'Native code calling glGetFloatv(' + name_ + ') and it returns undefined';
+ default:
+ throw 'Why did we hit the default case?';
+ }
+ },
+
+ glGetBooleanv: function(name_, p) {
+ 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":
+ throw 'Native code calling glGetBooleanv(' + name_ + ') on a name which returns a string!';
+ 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 {
+ throw 'Unknown object returned from WebGL getParameter';
+ }
+ break;
+ case "undefined":
+ throw 'Unknown object returned from WebGL getParameter';
+ default:
+ throw 'Why did we hit the default case?';
}
- // TODO complete
- {{{ makeSetValue('p', '0', 'v', 'i32') }}};
},
glGenTextures__deps: ['$GL'],
@@ -87,18 +212,98 @@ var LibraryGL = {
}
},
+ glCompressedTexImage2D: function(target, level, internalformat, width, height, border, imageSize, data) {
+ if (data) {
+ data = new Uint8Array(Array_copy(data, imageSize));
+ } else {
+ data = null;
+ }
+ Module.ctx.compressedTexImage2D(target, level, internalformat, width, height, border, data);
+ },
+
+ glCompressedTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, imageSize, data) {
+ if (data) {
+ data = new Uint8Array(Array_copy(data, imageSize));
+ } else {
+ data = null;
+ }
+ Module.ctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, data);
+ },
+
glTexImage2D: function(target, level, internalformat, width, height, border, format, type, pixels) {
if (pixels) {
- pixels = new Uint8Array(Array_copy(pixels, pixels + width*height*4)); // TODO: optimize
+ var sizePerPixel;
+ switch (type) {
+ case 0x1401 /* GL_UNSIGNED_BYTE */:
+ switch (format) {
+ case 0x1906 /* GL_ALPHA */:
+ case 0x1909 /* GL_LUMINANCE */:
+ sizePerPixel = 1;
+ break;
+ case 0x1907 /* GL_RGB */:
+ sizePerPixel = 3;
+ break;
+ case 0x1908 /* GL_RGBA */:
+ sizePerPixel = 4;
+ break;
+ case 0x190A /* GL_LUMINANCE_ALPHA */:
+ sizePerPixel = 2;
+ break;
+ default:
+ throw 'Invalid format (' + format + ') passed to glTexImage2D';
+ }
+ pixels = new Uint8Array(Array_copy(pixels, width*height*sizePerPixel));
+ break;
+ case 0x8363 /* GL_UNSIGNED_SHORT_5_6_5 */:
+ case 0x8033 /* GL_UNSIGNED_SHORT_4_4_4_4 */:
+ case 0x8034 /* GL_UNSIGNED_SHORT_5_5_5_1 */:
+ sizePerPixel = 2;
+ pixels = new Uint16Array(new ArrayBuffer(Array_copy(pixels, width*height*sizePerPixel*2)));
+ break;
+ default:
+ throw 'Invalid type (' + type + ') passed to glTexImage2D';
+ }
} else {
- pixels = new Uint8Array (width*height*4);
+ pixels = null;
}
Module.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
},
glTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, type, pixels) {
if (pixels) {
- pixels = new Uint8Array(Array_copy(pixels, pixels + width*height*4)); // TODO: optimize
+ var sizePerPixel;
+ switch (type) {
+ case 0x1401 /* GL_UNSIGNED_BYTE */:
+ switch (format) {
+ case 0x1906 /* GL_ALPHA */:
+ case 0x1909 /* GL_LUMINANCE */:
+ sizePerPixel = 1;
+ break;
+ case 0x1907 /* GL_RGB */:
+ sizePerPixel = 3;
+ break;
+ case 0x1908 /* GL_RGBA */:
+ sizePerPixel = 4;
+ break;
+ case 0x190A /* GL_LUMINANCE_ALPHA */:
+ sizePerPixel = 2;
+ break;
+ default:
+ throw 'Invalid format (' + format + ') passed to glTexSubImage2D';
+ }
+ pixels = new Uint8Array(Array_copy(pixels, (width-xoffset+1)*(height-yoffset+1)*sizePerPixel));
+ break;
+ case 0x8363 /* GL_UNSIGNED_SHORT_5_6_5 */:
+ case 0x8033 /* GL_UNSIGNED_SHORT_4_4_4_4 */:
+ case 0x8034 /* GL_UNSIGNED_SHORT_5_5_5_1 */:
+ sizePerPixel = 2;
+ pixels = new Uint16Array(new ArrayBuffer(Array_copy(pixels, (width-xoffset+1)*(height-yoffset+1)*sizePerPixel*2)));
+ break;
+ default:
+ throw 'Invalid type (' + type + ') passed to glTexSubImage2D';
+ }
+ } else {
+ pixels = null;
}
Module.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
},
@@ -107,6 +312,23 @@ var LibraryGL = {
Module.ctx.bindTexture(target, GL.hashtable("texture").get(texture));
},
+ glGetTexParameterfv: function(target, pname, params) {
+ {{{ makeSetValue('params', '0', 'Module.getTexParameter(target, pname)', 'float') }}};
+ },
+
+ glGetTexParameteriv: function(target, pname, params) {
+ {{{ makeSetValue('params', '0', 'Module.getTexParameter(target, pname)', 'i32') }}};
+ },
+
+ glIsTexture_deps: ['$GL'],
+ glIsTexture: function(texture) {
+ var fb = GL.hashtable("texture").get(texture);
+ if (typeof(fb) == 'undefined') {
+ return false;
+ }
+ return Module.ctx.isTexture(fb);
+ },
+
glGenBuffers__deps: ['$GL'],
glGenBuffers: function(n, buffers) {
for (var i = 0; i < n; i++) {
@@ -128,6 +350,53 @@ var LibraryGL = {
Module.ctx.bufferData(target, floatArray, usage);
},
+ glBufferSubData: function(target, offset, size, data) {
+ var floatArray = new Float32Array(TypedArray_copy(data, size, offset));
+ Module.ctx.bufferSubData(target, offset, floatArray);
+ },
+
+ glIsBuffer_deps: ['$GL'],
+ glIsBuffer: function(buffer) {
+ var fb = GL.hashtable("buffer").get(buffer);
+ if (typeof(fb) == 'undefined') {
+ return false;
+ }
+ return Module.ctx.isBuffer(fb);
+ },
+
+ glGenRenderbuffers__deps: ['$GL'],
+ glGenRenderbuffers: function(n, renderbuffers) {
+ for (var i = 0; i < n; i++) {
+ var id = GL.hashtable("renderbuffer").add(Module.ctx.createRenderbuffer());
+ {{{ makeSetValue('renderbuffers', 'i', 'id', 'i32') }}};
+ }
+ },
+
+ glDeleteRenderbuffers: function(n, renderbuffers) {
+ for (var i = 0; i < n; i++) {
+ var id = {{{ makeGetValue('renderbuffers', 'i', 'i32') }}};
+ Module.ctx.deleteRenderbuffer(GL.hashtable("renderbuffer").get(id));
+ GL.hashtable("renderbuffer").remove(id);
+ }
+ },
+
+ glBindRenderbuffer: function(target, renderbuffer) {
+ Module.ctx.bindRenderbuffer(target, GL.hashtable("renderbuffer").get(renderbuffer));
+ },
+
+ glGetRenderbufferParameteriv: function(target, pname, params) {
+ {{{ makeSetValue('params', '0', 'Module.ctx.getRenderbufferParameter(target, pname)', 'i32') }}};
+ },
+
+ glIsRenderbuffer_deps: ['$GL'],
+ glIsRenderbuffer: function(renderbuffer) {
+ var fb = GL.hashtable("renderbuffer").get(renderbuffer);
+ if (typeof(fb) == 'undefined') {
+ return false;
+ }
+ return Module.ctx.isRenderbuffer(fb);
+ },
+
glGetUniformLocation_deps: ['$GL'],
glGetUniformLocation: function(program, name) {
name = Pointer_stringify(name);
@@ -288,7 +557,24 @@ var LibraryGL = {
glDeleteShader_deps: ['$GL'],
glDeleteShader: function(shader) {
- return GL.hashtable("shader").remove(shader);
+ Module.ctx.deleteShader(GL.hashtable("shader").get(shader));
+ },
+
+ glDetachShader: function(program, shader) {
+ Module.ctx.detachShader(GL.hashtable("program").get(program),
+ GL.hashtable("shader").get(shader));
+ },
+
+ glGetAttachedShaders: function(program, maxCount, count, shaders) {
+ var result = Module.ctx.getAttachedShaders(GL.hashtable("program").get(program));
+ var len = result.length;
+ if (len > maxCount) {
+ len = maxCount;
+ }
+ {{{ makeSetValue('count', '0', 'len', 'i32') }}};
+ for (var i = 0; i < len; ++i) {
+ {{{ makeSetValue('shaders', 'i', 'GL.hashtable("shader").get(result[i])', 'i32') }}};
+ }
},
glShaderSource_deps: ['$GL'],
@@ -311,6 +597,15 @@ var LibraryGL = {
Module.ctx.shaderSource(GL.hashtable("shader").get(shader), source);
},
+ glGetShaderSource: function(shader, bufsize, length, source) {
+ var result = Module.ctx.getShaderSource(GL.hashtable("shader").get(shader));
+ result.slice(0, bufsize - 1);
+ writeStringToMemory(result, source);
+ if (length) {
+ {{{ makeSetValue('length', '0', 'result.length', 'i32') }}};
+ }
+ },
+
glCompileShader_deps: ['$GL'],
glCompileShader: function(shader) {
Module.ctx.compileShader(GL.hashtable("shader").get(shader));
@@ -322,18 +617,27 @@ var LibraryGL = {
log.slice(0, maxLength - 1);
writeStringToMemory(log, infoLog);
if (length) {
- {{{ makeSetValue('length', 'i', 'log.length', 'i32') }}}
+ {{{ makeSetValue('length', '0', 'log.length', 'i32') }}}
}
},
-
+
glGetShaderiv_deps: ['$GL'],
- glGetShaderiv : function(shader, pname, p) {
- {{{ makeSetValue('p', '0', 'Module.ctx.getShaderParameter(GL.hashtable("shader").get(shader),pname)', 'i32') }}};
+ glGetShaderiv : function(shader, pname, p) {
+ {{{ makeSetValue('p', '0', 'Module.ctx.getShaderParameter(GL.hashtable("shader").get(shader), pname)', 'i32') }}};
},
glGetProgramiv_deps: ['$GL'],
- glGetProgramiv : function(program, pname, p) {
- {{{ makeSetValue('p', '0', 'Module.ctx.getProgramParameter(GL.hashtable("program").get(program),pname)', 'i32') }}};
+ glGetProgramiv : function(program, pname, p) {
+ {{{ makeSetValue('p', '0', 'Module.ctx.getProgramParameter(GL.hashtable("program").get(program), pname)', 'i32') }}};
+ },
+
+ glIsShader_deps: ['$GL'],
+ glIsShader: function(shader) {
+ var fb = GL.hashtable("shader").get(shader);
+ if (typeof(fb) == 'undefined') {
+ return false;
+ }
+ return Module.ctx.isShader(fb);
},
glCreateProgram_deps: ['$GL'],
@@ -343,7 +647,7 @@ var LibraryGL = {
glDeleteProgram_deps: ['$GL'],
glDeleteProgram: function(program) {
- return GL.hashtable("program").remove(program);
+ Module.ctx.deleteProgram(GL.hashtable("program").get(program));
},
glAttachShader_deps: ['$GL'],
@@ -352,6 +656,13 @@ var LibraryGL = {
GL.hashtable("shader").get(shader));
},
+ glGetShaderPrecisionFormat: function(shaderType, precisionType, range, precision) {
+ var result = Module.ctx.getShaderPrecisionFormat(shaderType, precisionType);
+ {{{ makeSetValue('range', '0', 'result.rangeMin', 'i32') }}};
+ {{{ makeSetValue('range', '1', 'result.rangeMax', 'i32') }}};
+ {{{ makeSetValue('precision', '0', 'result.precision', 'i32') }}};
+ },
+
glLinkProgram_deps: ['$GL'],
glLinkProgram: function(program) {
Module.ctx.linkProgram(GL.hashtable("program").get(program));
@@ -367,7 +678,7 @@ var LibraryGL = {
log = log.substr(0, maxLength - 1);
writeStringToMemory(log, infoLog);
if (length) {
- {{{ makeSetValue('length', 'i', 'log.length', 'i32') }}}
+ {{{ makeSetValue('length', '0', 'log.length', 'i32') }}}
}
},
@@ -376,6 +687,20 @@ var LibraryGL = {
Module.ctx.useProgram(GL.hashtable("program").get(program));
},
+ glValidateProgram_deps: ['$Gl'],
+ glValidateProgram: function(program) {
+ Module.ctx.validateProgram(GL.hashtable("program").get(program));
+ },
+
+ glIsProgram_deps: ['$GL'],
+ glIsProgram: function(program) {
+ var fb = GL.hashtable("program").get(program);
+ if (typeof(fb) == 'undefined') {
+ return false;
+ }
+ return Module.ctx.isProgram(fb);
+ },
+
glBindAttribLocation_deps: ['$GL'],
glBindAttribLocation: function(program, index, name) {
name = Pointer_stringify(name);
@@ -435,12 +760,12 @@ var LibraryGL = {
// Simple pass-through functions
[[0, 'shadeModel fogi fogfv getError finish flush'],
- [1, 'clearDepth depthFunc enable disable frontFace cullFace clear enableVertexAttribArray disableVertexAttribArray lineWidth clearStencil depthMask stencilMask stencilMaskSeparate checkFramebufferStatus activeTexture'],
- [2, 'pixelStorei vertexAttrib1f depthRange polygonOffset blendFunc'],
+ [1, 'clearDepth depthFunc enable disable frontFace cullFace clear enableVertexAttribArray disableVertexAttribArray lineWidth clearStencil depthMask stencilMask stencilMaskSeparate checkFramebufferStatus generateMipmap activeTexture'],
[3, 'texParameteri texParameterf drawArrays vertexAttrib2f'],
- [4, 'viewport clearColor scissor vertexAttrib3f colorMask drawElements'],
+ [4, 'viewport clearColor scissor vertexAttrib3f colorMask drawElements renderbufferStorage'],
[5, 'vertexAttrib4f'],
- [6, 'vertexAttribPointer']].forEach(function(data) {
+ [6, 'vertexAttribPointer'],
+ [8, 'copyTexImage2D copyTexSubImage2D']].forEach(function(data) {
var num = data[0];
var names = data[1];
var args = range(num).map(function(i) { return 'x' + i }).join(', ');
@@ -718,6 +1043,46 @@ var LibraryGLUT = {
};
+var LibraryXlib = {
+ XOpenDisplay: function() {
+ return 1; // We support 1 display, the canvas
+ },
+
+ XCreateWindow: function(display, parent, x, y, width, height, border_width, depth, class_, visual, valuemask, attributes) {
+ // All we can do is set the width and height
+ Module['canvas'].width = width;
+ Module['canvas'].height = height;
+ return 2;
+ },
+
+ XChangeWindowAttributes: function(){},
+ XSetWMHints: function(){},
+ XMapWindow: function(){},
+ XStoreName: function(){},
+ XInternAtom: function(display, name_, hmm) { return 0 },
+ XSendEvent: function(){},
+ XPending: function(display) { return 0 },
+};
+
+var LibraryEGL = {
+ eglGetDisplay: function(x_display) { return 3 },
+ eglInitialize: function(display, majorVersion, minorVersion) { return 1 },
+ eglGetConfigs: function(display, hmm1, hmm2, numConfigs) { return 1 },
+ eglChooseConfig: function(display, attribList, config, hmm, numConfigs) { return 1 },
+ eglCreateWindowSurface: function(display, config, hWnd, hmm) { return 4 },
+
+ eglCreateContext__deps: ['glutCreateWindow', '$GL'],
+ eglCreateContext: function(display, config, hmm, contextAttribs) {
+ _glutCreateWindow();
+ return 1;
+ },
+
+ eglMakeCurrent: function(display, surface, surface, context) { return 1 },
+ eglSwapBuffers: function() {},
+};
+
mergeInto(LibraryManager.library, LibraryGL);
mergeInto(LibraryManager.library, LibraryGLUT);
+mergeInto(LibraryManager.library, LibraryXlib);
+mergeInto(LibraryManager.library, LibraryEGL);
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 9d947cd4..631de481 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -90,6 +90,7 @@ mergeInto(LibraryManager.library, {
fonts: [null],
keyboardState: null,
+ startTime: null,
mouseX: 0,
mouseY: 0,
@@ -98,6 +99,7 @@ mergeInto(LibraryManager.library, {
40: 1105, // down arrow
37: 1104, // left arrow
39: 1103, // right arrow
+
17: 305, // control (right, or left)
18: 308, // alt
109: 45, // minus
@@ -378,7 +380,13 @@ mergeInto(LibraryManager.library, {
return 0; // success
},
- SDL_WasInit: function() { return 0 }, // TODO
+ SDL_WasInit__deps: ['SDL_Init'],
+ SDL_WasInit: function() {
+ if (SDL.startTime === null) {
+ _SDL_Init();
+ }
+ return 1;
+ },
SDL_GetVideoInfo: function() {
// %struct.SDL_VideoInfo = type { i32, i32, %struct.SDL_PixelFormat*, i32, i32 } - 5 fields of quantum size
@@ -409,6 +417,9 @@ mergeInto(LibraryManager.library, {
},
SDL_Quit: function() {
+ for (var i = 0; i < SDL.audios; i++) {
+ SDL.audios[i].pause();
+ }
Module.print('SDL_Quit called (and ignored)');
},
@@ -460,13 +471,14 @@ mergeInto(LibraryManager.library, {
assert(buffer % 4 == 0, 'Invalid buffer offset: ' + buffer);
var src = buffer >> 2;
var dst = 0;
+ var isScreen = surf == SDL.screen;
while (dst < num) {
// TODO: access underlying data buffer and write in 32-bit chunks or more
var val = HEAP32[src]; // This is optimized. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
- data[dst] = val & 0xff;
+ data[dst ] = val & 0xff;
data[dst+1] = (val >> 8) & 0xff;
data[dst+2] = (val >> 16) & 0xff;
- data[dst+3] = (val >> 24) & 0xff;
+ data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
src++;
dst += 4;
}
@@ -717,15 +729,14 @@ mergeInto(LibraryManager.library, {
SDL_CondWait: function() {},
SDL_DestroyCond: function() {},
-//SDL_CreateYUVOverlay
-//SDL_CreateThread, SDL_WaitThread etc
-
// SDL Mixer
- Mix_OpenAudio: function() { return 0 },
+ Mix_OpenAudio: function(frequency, format, channels, chunksize) {
+ return 0;
+ },
Mix_HookMusicFinished: function(func) {
- SDL.hookMusicFinished = func; // TODO: use this
+ SDL.hookMusicFinished = func;
},
Mix_VolumeMusic: function(func) {
@@ -734,46 +745,39 @@ mergeInto(LibraryManager.library, {
Mix_LoadWAV_RW: function(filename, freesrc) {
filename = FS.standardizePath(Pointer_stringify(filename));
+ var raw = preloadedAudios[filename];
+ assert(raw, 'Cannot find preloaded audio ' + filename);
var id = SDL.audios.length;
SDL.audios.push({
- audio: new Audio(filename)
+ source: filename,
+ audio: raw
});
return id;
},
Mix_FreeChunk: function(id) {
- //SDL.audios[id].audio.pause();
- //SDL.audios[id] = null;
- return 0;
+ SDL.audios[id].audio.pause();
+ SDL.audios[id] = null;
},
Mix_PlayChannel: function(channel, id, loops) {
- //var audio = SDL.audios[id].audio;
- //audio.play();
- return 0; // XXX should return channel
+ // TODO: handle loops
+ var audio = SDL.audios[id].audio;
+ if (audio.currentTime) audio.src = audio.src; // This hack prevents lags on replaying // TODO: parallel sounds through //cloneNode(true).play()
+ audio.play();
+ return 1; // XXX should return channel
},
Mix_PlayChannelTimed: 'Mix_PlayChannel', // XXX ignore Timing
- Mix_LoadMUS: function(filename) {
- filename = FS.standardizePath(Pointer_stringify(filename));
- var id = SDL.audios.length;
- SDL.audios.push({
- audio: new Audio(filename)
- });
- return id;
- },
-
- Mix_FreeMusic: function(id) {
- SDL.audios[id].audio.pause();
- SDL.audios[id] = null;
- return 0;
- },
+ Mix_LoadMUS: 'Mix_LoadWAV_RW',
+ Mix_FreeMusic: 'Mix_FreeChunk',
Mix_PlayMusic: function(id, loops) {
- if (loops == 0) return;
+ loops = Math.max(loops, 1);
var audio = SDL.audios[id].audio;
- audio.loop = loop != 1; // TODO: handle N loops for finite N
+ audio.loop = loops != 1; // TODO: handle N loops for finite N
audio.play();
+ SDL.music = audio;
return 0;
},
@@ -789,15 +793,21 @@ mergeInto(LibraryManager.library, {
return 0;
},
- Mix_HaltMusic: function(id) {
- var audio = SDL.audios[id].audio;
- audio.pause(); // TODO: actually rewind to the beginning
+ Mix_HaltMusic: function() {
+ var audio = SDL.music;
+ if (!audio) return 0;
+ audio.src = audio.src; // rewind
+ audio.pause();
+ SDL.music = null;
+ if (SDL.hookMusicFinished) {
+ FUNCTION_TABLE[SDL.hookMusicFinished]();
+ }
return 0;
},
Mix_FadeInMusicPos: 'Mix_PlayMusic', // XXX ignore fading in effect
- Mix_FadeOutMusic: function(id) {}, // TODO
+ Mix_FadeOutMusic: 'Mix_HaltMusic', // XXX ignore fading out effect
// SDL TTF
diff --git a/src/long.js b/src/long.js
new file mode 100644
index 00000000..71cffa79
--- /dev/null
+++ b/src/long.js
@@ -0,0 +1,1633 @@
+// TODO: strip out parts of this we do not need
+
+//======= begin closure i64 code =======
+
+// Copyright 2009 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//