summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library_egl.js8
-rw-r--r--src/library_fs.js172
-rw-r--r--src/library_gl.js8
-rw-r--r--src/library_glfw.js4
-rw-r--r--src/library_glut.js4
-rw-r--r--src/library_idbfs.js2
-rw-r--r--src/library_memfs.js98
-rw-r--r--src/library_nodefs.js12
-rw-r--r--src/library_path.js22
-rw-r--r--src/library_sdl.js6
-rw-r--r--src/preamble.js10
-rw-r--r--src/shell.html5
-rw-r--r--tests/aniso.c3
-rw-r--r--tests/test_browser.py42
-rw-r--r--tests/test_webgl_context_attributes_common.c262
-rw-r--r--tests/test_webgl_context_attributes_glfw.c47
-rw-r--r--tests/test_webgl_context_attributes_glut.c42
-rw-r--r--tests/test_webgl_context_attributes_sdl.c50
-rw-r--r--tools/file_packager.py39
19 files changed, 673 insertions, 163 deletions
diff --git a/src/library_egl.js b/src/library_egl.js
index 69902785..cc702fec 100644
--- a/src/library_egl.js
+++ b/src/library_egl.js
@@ -421,10 +421,10 @@ var LibraryEGL = {
if (EGL.stringCache[name]) return EGL.stringCache[name];
var ret;
switch(name) {
- case 0x3053 /* EGL_VENDOR */: ret = allocate(intArrayFromString("Emscripten"), 'i8', ALLOC_NORMAL);
- case 0x3054 /* EGL_VERSION */: ret = allocate(intArrayFromString("1.4 Emscripten EGL"), 'i8', ALLOC_NORMAL);
- case 0x3055 /* EGL_EXTENSIONS */: ret = allocate(intArrayFromString(""), 'i8', ALLOC_NORMAL); // Currently not supporting any EGL extensions.
- case 0x308D /* EGL_CLIENT_APIS */: ret = allocate(intArrayFromString("OpenGL_ES"), 'i8', ALLOC_NORMAL);
+ case 0x3053 /* EGL_VENDOR */: ret = allocate(intArrayFromString("Emscripten"), 'i8', ALLOC_NORMAL); break;
+ case 0x3054 /* EGL_VERSION */: ret = allocate(intArrayFromString("1.4 Emscripten EGL"), 'i8', ALLOC_NORMAL); break;
+ case 0x3055 /* EGL_EXTENSIONS */: ret = allocate(intArrayFromString(""), 'i8', ALLOC_NORMAL); break; // Currently not supporting any EGL extensions.
+ case 0x308D /* EGL_CLIENT_APIS */: ret = allocate(intArrayFromString("OpenGL_ES"), 'i8', ALLOC_NORMAL); break;
default:
EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);
return 0;
diff --git a/src/library_fs.js b/src/library_fs.js
index bd1522a8..aece2664 100644
--- a/src/library_fs.js
+++ b/src/library_fs.js
@@ -28,6 +28,7 @@ mergeInto(LibraryManager.library, {
ignorePermissions: true,
ErrnoError: null, // set during init
+ genericErrors: {},
handleFSError: function(e) {
if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace();
@@ -62,7 +63,7 @@ mergeInto(LibraryManager.library, {
}
current = FS.lookupNode(current, parts[i]);
- current_path = PATH.join(current_path, parts[i]);
+ current_path = PATH.join2(current_path, parts[i]);
// jump to the mount's root node if this is a mountpoint
if (FS.isMountpoint(current)) {
@@ -94,9 +95,11 @@ mergeInto(LibraryManager.library, {
var path;
while (true) {
if (FS.isRoot(node)) {
- return path ? PATH.join(node.mount.mountpoint, path) : node.mount.mountpoint;
+ var mount = node.mount.mountpoint;
+ if (!path) return mount;
+ return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path;
}
- path = path ? PATH.join(node.name, path) : node.name;
+ path = path ? node.name + '/' + path : node.name;
node = node.parent;
}
},
@@ -158,44 +161,50 @@ mergeInto(LibraryManager.library, {
return FS.lookup(parent, name);
},
createNode: function(parent, name, mode, rdev) {
- var node = {
- id: FS.nextInode++,
- name: name,
- mode: mode,
- node_ops: {},
- stream_ops: {},
- rdev: rdev,
- parent: null,
- mount: null
- };
- if (!parent) {
- parent = node; // root node sets parent to itself
- }
- node.parent = parent;
- node.mount = parent.mount;
- // compatibility
- var readMode = {{{ cDefine('S_IRUGO') }}} | {{{ cDefine('S_IXUGO') }}};
- var writeMode = {{{ cDefine('S_IWUGO') }}};
- // NOTE we must use Object.defineProperties instead of individual calls to
- // Object.defineProperty in order to make closure compiler happy
- Object.defineProperties(node, {
- read: {
- get: function() { return (node.mode & readMode) === readMode; },
- set: function(val) { val ? node.mode |= readMode : node.mode &= ~readMode; }
- },
- write: {
- get: function() { return (node.mode & writeMode) === writeMode; },
- set: function(val) { val ? node.mode |= writeMode : node.mode &= ~writeMode; }
- },
- isFolder: {
- get: function() { return FS.isDir(node.mode); },
- },
- isDevice: {
- get: function() { return FS.isChrdev(node.mode); },
- },
- });
- FS.hashAddNode(node);
- return node;
+ if (!FS.FSNode) {
+ FS.FSNode = function(parent, name, mode, rdev) {
+ this.id = FS.nextInode++;
+ this.name = name;
+ this.mode = mode;
+ this.node_ops = {};
+ this.stream_ops = {};
+ this.rdev = rdev;
+ this.parent = null;
+ this.mount = null;
+ if (!parent) {
+ parent = this; // root node sets parent to itself
+ }
+ this.parent = parent;
+ this.mount = parent.mount;
+ FS.hashAddNode(this);
+ };
+
+ // compatibility
+ var readMode = {{{ cDefine('S_IRUGO') }}} | {{{ cDefine('S_IXUGO') }}};
+ var writeMode = {{{ cDefine('S_IWUGO') }}};
+
+ FS.FSNode.prototype = {};
+
+ // NOTE we must use Object.defineProperties instead of individual calls to
+ // Object.defineProperty in order to make closure compiler happy
+ Object.defineProperties(FS.FSNode.prototype, {
+ read: {
+ get: function() { return (this.mode & readMode) === readMode; },
+ set: function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; }
+ },
+ write: {
+ get: function() { return (this.mode & writeMode) === writeMode; },
+ set: function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; }
+ },
+ isFolder: {
+ get: function() { return FS.isDir(this.mode); },
+ },
+ isDevice: {
+ get: function() { return FS.isChrdev(this.mode); },
+ },
+ });
+ }
+ return new FS.FSNode(parent, name, mode, rdev);
},
destroyNode: function(node) {
FS.hashRemoveNode(node);
@@ -351,24 +360,28 @@ mergeInto(LibraryManager.library, {
// object isn't directly passed in. not possible until
// SOCKFS is completed.
createStream: function(stream, fd_start, fd_end) {
+ if (!FS.FSStream) {
+ FS.FSStream = {};
+ // compatibility
+ Object.defineProperties(FS.FSStream, {
+ object: {
+ get: function() { return this.node; },
+ set: function(val) { this.node = val; }
+ },
+ isRead: {
+ get: function() { return (this.flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_WRONLY') }}}; }
+ },
+ isWrite: {
+ get: function() { return (this.flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_RDONLY') }}}; }
+ },
+ isAppend: {
+ get: function() { return (this.flags & {{{ cDefine('O_APPEND') }}}); }
+ }
+ });
+ }
+ stream.prototype = FS.FSStream;
var fd = FS.nextfd(fd_start, fd_end);
stream.fd = fd;
- // compatibility
- Object.defineProperties(stream, {
- object: {
- get: function() { return stream.node; },
- set: function(val) { stream.node = val; }
- },
- isRead: {
- get: function() { return (stream.flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_WRONLY') }}}; }
- },
- isWrite: {
- get: function() { return (stream.flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_RDONLY') }}}; }
- },
- isAppend: {
- get: function() { return (stream.flags & {{{ cDefine('O_APPEND') }}}); }
- }
- });
FS.streams[fd] = stream;
return stream;
},
@@ -771,7 +784,6 @@ mergeInto(LibraryManager.library, {
});
},
open: function(path, flags, mode, fd_start, fd_end) {
- path = PATH.normalize(path);
flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags;
mode = typeof mode === 'undefined' ? 0666 : mode;
if ((flags & {{{ cDefine('O_CREAT') }}})) {
@@ -780,13 +792,18 @@ mergeInto(LibraryManager.library, {
mode = 0;
}
var node;
- try {
- var lookup = FS.lookupPath(path, {
- follow: !(flags & {{{ cDefine('O_NOFOLLOW') }}})
- });
- node = lookup.node;
- } catch (e) {
- // ignore
+ if (typeof path === 'object') {
+ node = path;
+ } else {
+ path = PATH.normalize(path);
+ try {
+ var lookup = FS.lookupPath(path, {
+ follow: !(flags & {{{ cDefine('O_NOFOLLOW') }}})
+ });
+ node = lookup.node;
+ } catch (e) {
+ // ignore
+ }
}
// perhaps we need to create the node
if ((flags & {{{ cDefine('O_CREAT') }}})) {
@@ -1079,6 +1096,11 @@ mergeInto(LibraryManager.library, {
};
FS.ErrnoError.prototype = new Error();
FS.ErrnoError.prototype.constructor = FS.ErrnoError;
+ // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info)
+ [ERRNO_CODES.ENOENT].forEach(function(code) {
+ FS.genericErrors[code] = new FS.ErrnoError(code);
+ FS.genericErrors[code].stack = '<generic error, no stack>';
+ });
},
staticInit: function() {
FS.ensureErrnoError();
@@ -1173,7 +1195,7 @@ mergeInto(LibraryManager.library, {
return ret;
},
createFolder: function(parent, name, canRead, canWrite) {
- var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
var mode = FS.getMode(canRead, canWrite);
return FS.mkdir(path, mode);
},
@@ -1183,7 +1205,7 @@ mergeInto(LibraryManager.library, {
while (parts.length) {
var part = parts.pop();
if (!part) continue;
- var current = PATH.join(parent, part);
+ var current = PATH.join2(parent, part);
try {
FS.mkdir(current);
} catch (e) {
@@ -1194,12 +1216,12 @@ mergeInto(LibraryManager.library, {
return current;
},
createFile: function(parent, name, properties, canRead, canWrite) {
- var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
var mode = FS.getMode(canRead, canWrite);
return FS.create(path, mode);
},
createDataFile: function(parent, name, data, canRead, canWrite, canOwn) {
- var path = name ? PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent;
+ var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent;
var mode = FS.getMode(canRead, canWrite);
var node = FS.create(path, mode);
if (data) {
@@ -1209,16 +1231,16 @@ mergeInto(LibraryManager.library, {
data = arr;
}
// make sure we can write to the file
- FS.chmod(path, mode | {{{ cDefine('S_IWUGO') }}});
- var stream = FS.open(path, 'w');
+ FS.chmod(node, mode | {{{ cDefine('S_IWUGO') }}});
+ var stream = FS.open(node, 'w');
FS.write(stream, data, 0, data.length, 0, canOwn);
FS.close(stream);
- FS.chmod(path, mode);
+ FS.chmod(node, mode);
}
return node;
},
createDevice: function(parent, name, input, output) {
- var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
var mode = FS.getMode(!!input, !!output);
if (!FS.createDevice.major) FS.createDevice.major = 64;
var dev = FS.makedev(FS.createDevice.major++, 0);
@@ -1272,7 +1294,7 @@ mergeInto(LibraryManager.library, {
return FS.mkdev(path, mode, dev);
},
createLink: function(parent, name, target, canRead, canWrite) {
- var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
return FS.symlink(target, path);
},
// Makes sure a file's contents are loaded. Returns whether the file has
@@ -1462,7 +1484,7 @@ mergeInto(LibraryManager.library, {
Browser.init();
// TODO we should allow people to just pass in a complete filename instead
// of parent and name being that we just join them anyways
- var fullname = name ? PATH.resolve(PATH.join(parent, name)) : parent;
+ var fullname = name ? PATH.resolve(PATH.join2(parent, name)) : parent;
function processData(byteArray) {
function finish(byteArray) {
if (!dontCreateFile) {
diff --git a/src/library_gl.js b/src/library_gl.js
index cfdd800d..544a33db 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -506,6 +506,7 @@ var LibraryGL = {
case 0x1F01 /* GL_RENDERER */:
case 0x1F02 /* GL_VERSION */:
ret = allocate(intArrayFromString(Module.ctx.getParameter(name_)), 'i8', ALLOC_NORMAL);
+ break;
case 0x1F03 /* GL_EXTENSIONS */:
var exts = Module.ctx.getSupportedExtensions();
var gl_exts = [];
@@ -514,8 +515,10 @@ var LibraryGL = {
gl_exts.push("GL_" + exts[i]);
}
ret = allocate(intArrayFromString(gl_exts.join(' ')), 'i8', ALLOC_NORMAL);
+ break;
case 0x8B8C /* GL_SHADING_LANGUAGE_VERSION */:
ret = allocate(intArrayFromString('OpenGL ES GLSL 1.00 (WebGL)'), 'i8', ALLOC_NORMAL);
+ break;
default:
throw 'Failure: Invalid glGetString value: ' + name_;
}
@@ -1800,13 +1803,16 @@ var LibraryGL = {
var glGetString = _glGetString;
_glGetString = function(name_) {
+ if (GL.stringCache[name_]) return GL.stringCache[name_];
switch(name_) {
case 0x1F03 /* GL_EXTENSIONS */: // Add various extensions that we can support
- return allocate(intArrayFromString(Module.ctx.getSupportedExtensions().join(' ') +
+ var ret = allocate(intArrayFromString(Module.ctx.getSupportedExtensions().join(' ') +
' GL_EXT_texture_env_combine GL_ARB_texture_env_crossbar GL_ATI_texture_env_combine3 GL_NV_texture_env_combine4 GL_EXT_texture_env_dot3 GL_ARB_multitexture GL_ARB_vertex_buffer_object GL_EXT_framebuffer_object GL_ARB_vertex_program GL_ARB_fragment_program GL_ARB_shading_language_100 GL_ARB_shader_objects GL_ARB_vertex_shader GL_ARB_fragment_shader GL_ARB_texture_cube_map GL_EXT_draw_range_elements' +
(GL.compressionExt ? ' GL_ARB_texture_compression GL_EXT_texture_compression_s3tc' : '') +
(GL.anisotropicExt ? ' GL_EXT_texture_filter_anisotropic' : '')
), 'i8', ALLOC_NORMAL);
+ GL.stringCache[name_] = ret;
+ return ret;
}
return glGetString(name_);
};
diff --git a/src/library_glfw.js b/src/library_glfw.js
index b0519e39..647d4bb6 100644
--- a/src/library_glfw.js
+++ b/src/library_glfw.js
@@ -355,7 +355,9 @@ var LibraryGLFW = {
}
var contextAttributes = {
- antialias: (GLFW.params[0x00020013] > 1) //GLFW_FSAA_SAMPLES
+ antialias: (GLFW.params[0x00020013] > 1), //GLFW_FSAA_SAMPLES
+ depth: (GLFW.params[0x00020009] > 0), //GLFW_DEPTH_BITS
+ stencil: (GLFW.params[0x0002000A] > 0) //GLFW_STENCIL_BITS
}
Module.ctx = Browser.createContext(Module['canvas'], true, true, contextAttributes);
return 1; //GL_TRUE
diff --git a/src/library_glut.js b/src/library_glut.js
index 722ea85c..fefe7bd3 100644
--- a/src/library_glut.js
+++ b/src/library_glut.js
@@ -427,7 +427,9 @@ var LibraryGLUT = {
glutCreateWindow__deps: ['$Browser'],
glutCreateWindow: function(name) {
var contextAttributes = {
- antialias: ((GLUT.initDisplayMode & 0x0080 /*GLUT_MULTISAMPLE*/) != 0)
+ antialias: ((GLUT.initDisplayMode & 0x0080 /*GLUT_MULTISAMPLE*/) != 0),
+ depth: ((GLUT.initDisplayMode & 0x0010 /*GLUT_DEPTH*/) != 0),
+ stencil: ((GLUT.initDisplayMode & 0x0020 /*GLUT_STENCIL*/) != 0)
};
Module.ctx = Browser.createContext(Module['canvas'], true, true, contextAttributes);
return Module.ctx ? 1 /* a new GLUT window ID for the created context */ : 0 /* failure */;
diff --git a/src/library_idbfs.js b/src/library_idbfs.js
index 9031bad8..ab55673f 100644
--- a/src/library_idbfs.js
+++ b/src/library_idbfs.js
@@ -130,7 +130,7 @@ mergeInto(LibraryManager.library, {
};
var toAbsolute = function(root) {
return function(p) {
- return PATH.join(root, p);
+ return PATH.join2(root, p);
}
};
diff --git a/src/library_memfs.js b/src/library_memfs.js
index 94fd767e..588bbabd 100644
--- a/src/library_memfs.js
+++ b/src/library_memfs.js
@@ -1,6 +1,8 @@
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
@@ -13,51 +15,71 @@ mergeInto(LibraryManager.library, {
// no supported
throw new FS.ErrnoError(ERRNO_CODES.EPERM);
}
+ if (!MEMFS.ops_table) {
+ MEMFS.ops_table = {
+ dir: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr,
+ lookup: MEMFS.node_ops.lookup,
+ mknod: MEMFS.node_ops.mknod,
+ mknod: MEMFS.node_ops.mknod,
+ rename: MEMFS.node_ops.rename,
+ unlink: MEMFS.node_ops.unlink,
+ rmdir: MEMFS.node_ops.rmdir,
+ readdir: MEMFS.node_ops.readdir,
+ symlink: MEMFS.node_ops.symlink
+ },
+ stream: {
+ llseek: MEMFS.stream_ops.llseek
+ }
+ },
+ file: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr
+ },
+ stream: {
+ llseek: MEMFS.stream_ops.llseek,
+ read: MEMFS.stream_ops.read,
+ write: MEMFS.stream_ops.write,
+ allocate: MEMFS.stream_ops.allocate,
+ mmap: MEMFS.stream_ops.mmap
+ }
+ },
+ link: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr,
+ readlink: MEMFS.node_ops.readlink
+ },
+ stream: {}
+ },
+ chrdev: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr
+ },
+ stream: FS.chrdev_stream_ops
+ },
+ };
+ }
var node = FS.createNode(parent, name, mode, dev);
if (FS.isDir(node.mode)) {
- node.node_ops = {
- getattr: MEMFS.node_ops.getattr,
- setattr: MEMFS.node_ops.setattr,
- lookup: MEMFS.node_ops.lookup,
- mknod: MEMFS.node_ops.mknod,
- mknod: MEMFS.node_ops.mknod,
- rename: MEMFS.node_ops.rename,
- unlink: MEMFS.node_ops.unlink,
- rmdir: MEMFS.node_ops.rmdir,
- readdir: MEMFS.node_ops.readdir,
- symlink: MEMFS.node_ops.symlink
- };
- node.stream_ops = {
- llseek: MEMFS.stream_ops.llseek
- };
+ node.node_ops = MEMFS.ops_table.dir.node;
+ node.stream_ops = MEMFS.ops_table.dir.stream;
node.contents = {};
} else if (FS.isFile(node.mode)) {
- node.node_ops = {
- getattr: MEMFS.node_ops.getattr,
- setattr: MEMFS.node_ops.setattr
- };
- node.stream_ops = {
- llseek: MEMFS.stream_ops.llseek,
- read: MEMFS.stream_ops.read,
- write: MEMFS.stream_ops.write,
- allocate: MEMFS.stream_ops.allocate,
- mmap: MEMFS.stream_ops.mmap
- };
+ node.node_ops = MEMFS.ops_table.file.node;
+ node.stream_ops = MEMFS.ops_table.file.stream;
node.contents = [];
node.contentMode = MEMFS.CONTENT_FLEXIBLE;
} else if (FS.isLink(node.mode)) {
- node.node_ops = {
- getattr: MEMFS.node_ops.getattr,
- setattr: MEMFS.node_ops.setattr,
- readlink: MEMFS.node_ops.readlink
- };
- node.stream_ops = {};
+ node.node_ops = MEMFS.ops_table.link.node;
+ node.stream_ops = MEMFS.ops_table.link.stream;
} else if (FS.isChrdev(node.mode)) {
- node.node_ops = {
- getattr: MEMFS.node_ops.getattr,
- setattr: MEMFS.node_ops.setattr
- };
- node.stream_ops = FS.chrdev_stream_ops;
+ node.node_ops = MEMFS.ops_table.chrdev.node;
+ node.stream_ops = MEMFS.ops_table.chrdev.stream;
}
node.timestamp = Date.now();
// add the new node to the parent
@@ -117,7 +139,7 @@ mergeInto(LibraryManager.library, {
}
},
lookup: function(parent, name) {
- throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
+ throw FS.genericErrors[ERRNO_CODES.ENOENT];
},
mknod: function(parent, name, mode, dev) {
return MEMFS.createNode(parent, name, mode, dev);
diff --git a/src/library_nodefs.js b/src/library_nodefs.js
index 2be54076..7686f3f2 100644
--- a/src/library_nodefs.js
+++ b/src/library_nodefs.js
@@ -134,7 +134,7 @@ mergeInto(LibraryManager.library, {
}
},
lookup: function (parent, name) {
- var path = PATH.join(NODEFS.realPath(parent), name);
+ var path = PATH.join2(NODEFS.realPath(parent), name);
var mode = NODEFS.getMode(path);
return NODEFS.createNode(parent, name, mode);
},
@@ -156,7 +156,7 @@ mergeInto(LibraryManager.library, {
},
rename: function (oldNode, newDir, newName) {
var oldPath = NODEFS.realPath(oldNode);
- var newPath = PATH.join(NODEFS.realPath(newDir), newName);
+ var newPath = PATH.join2(NODEFS.realPath(newDir), newName);
try {
fs.renameSync(oldPath, newPath);
} catch (e) {
@@ -165,7 +165,7 @@ mergeInto(LibraryManager.library, {
}
},
unlink: function(parent, name) {
- var path = PATH.join(NODEFS.realPath(parent), name);
+ var path = PATH.join2(NODEFS.realPath(parent), name);
try {
fs.unlinkSync(path);
} catch (e) {
@@ -174,7 +174,7 @@ mergeInto(LibraryManager.library, {
}
},
rmdir: function(parent, name) {
- var path = PATH.join(NODEFS.realPath(parent), name);
+ var path = PATH.join2(NODEFS.realPath(parent), name);
try {
fs.rmdirSync(path);
} catch (e) {
@@ -192,7 +192,7 @@ mergeInto(LibraryManager.library, {
}
},
symlink: function(parent, newName, oldPath) {
- var newPath = PATH.join(NODEFS.realPath(parent), newName);
+ var newPath = PATH.join2(NODEFS.realPath(parent), newName);
try {
fs.symlinkSync(oldPath, newPath);
} catch (e) {
@@ -283,4 +283,4 @@ mergeInto(LibraryManager.library, {
}
}
}
-}); \ No newline at end of file
+});
diff --git a/src/library_path.js b/src/library_path.js
index 09808acd..f00a7586 100644
--- a/src/library_path.js
+++ b/src/library_path.js
@@ -59,26 +59,22 @@ mergeInto(LibraryManager.library, {
}
return root + dir;
},
- basename: function(path, ext) {
+ basename: function(path) {
// EMSCRIPTEN return '/'' for '/', not an empty string
if (path === '/') return '/';
- var f = PATH.splitPath(path)[2];
- if (ext && f.substr(-1 * ext.length) === ext) {
- f = f.substr(0, f.length - ext.length);
- }
- return f;
+ var lastSlash = path.lastIndexOf('/');
+ if (lastSlash === -1) return path;
+ return path.substr(lastSlash+1);
},
extname: function(path) {
return PATH.splitPath(path)[3];
},
join: function() {
var paths = Array.prototype.slice.call(arguments, 0);
- return PATH.normalize(paths.filter(function(p, index) {
- if (typeof p !== 'string') {
- throw new TypeError('Arguments to path.join must be strings');
- }
- return p;
- }).join('/'));
+ return PATH.normalize(paths.join('/'));
+ },
+ join2: function(l, r) {
+ return PATH.normalize(l + '/' + r);
},
resolve: function() {
var resolvedPath = '',
@@ -134,4 +130,4 @@ mergeInto(LibraryManager.library, {
return outputParts.join('/');
}
}
-}); \ No newline at end of file
+});
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 857ab7d4..e652dfc8 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -254,9 +254,13 @@ var LibrarySDL = {
}
var webGLContextAttributes = {
- antialias: ((SDL.glAttributes[13 /*SDL_GL_MULTISAMPLEBUFFERS*/] != 0) && (SDL.glAttributes[14 /*SDL_GL_MULTISAMPLESAMPLES*/] > 1))
+ antialias: ((SDL.glAttributes[13 /*SDL_GL_MULTISAMPLEBUFFERS*/] != 0) && (SDL.glAttributes[14 /*SDL_GL_MULTISAMPLESAMPLES*/] > 1)),
+ depth: (SDL.glAttributes[6 /*SDL_GL_DEPTH_SIZE*/] > 0),
+ stencil: (SDL.glAttributes[7 /*SDL_GL_STENCIL_SIZE*/] > 0)
};
+
var ctx = Browser.createContext(canvas, useWebGL, usePageCanvas, webGLContextAttributes);
+
SDL.surfaces[surf] = {
width: width,
height: height,
diff --git a/src/preamble.js b/src/preamble.js
index ee273f6a..9e72e7b8 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -1107,19 +1107,21 @@ var Math_min = Math.min;
// it happens right before run - run will be postponed until
// the dependencies are met.
var runDependencies = 0;
-var runDependencyTracking = {};
var runDependencyWatcher = null;
var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
+#if ASSERTIONS
+var runDependencyTracking = {};
+#endif
function addRunDependency(id) {
runDependencies++;
if (Module['monitorRunDependencies']) {
Module['monitorRunDependencies'](runDependencies);
}
+#if ASSERTIONS
if (id) {
assert(!runDependencyTracking[id]);
runDependencyTracking[id] = 1;
-#if ASSERTIONS
if (runDependencyWatcher === null && typeof setInterval !== 'undefined') {
// Check for missing dependencies every few seconds
runDependencyWatcher = setInterval(function() {
@@ -1136,10 +1138,10 @@ function addRunDependency(id) {
}
}, 10000);
}
-#endif
} else {
Module.printErr('warning: run dependency added without ID');
}
+#endif
}
Module['addRunDependency'] = addRunDependency;
function removeRunDependency(id) {
@@ -1147,12 +1149,14 @@ function removeRunDependency(id) {
if (Module['monitorRunDependencies']) {
Module['monitorRunDependencies'](runDependencies);
}
+#if ASSERTIONS
if (id) {
assert(runDependencyTracking[id]);
delete runDependencyTracking[id];
} else {
Module.printErr('warning: run dependency removed without ID');
}
+#endif
if (runDependencies == 0) {
if (runDependencyWatcher !== null) {
clearInterval(runDependencyWatcher);
diff --git a/src/shell.html b/src/shell.html
index a33735d9..53a4fffb 100644
--- a/src/shell.html
+++ b/src/shell.html
@@ -63,8 +63,11 @@
},
canvas: document.getElementById('canvas'),
setStatus: function(text) {
- if (Module.setStatus.interval) clearInterval(Module.setStatus.interval);
+ if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
+ if (text === Module.setStatus.text) return;
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+ var now = Date.now();
+ if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');
if (m) {
diff --git a/tests/aniso.c b/tests/aniso.c
index e8d7bd3f..f1674cad 100644
--- a/tests/aniso.c
+++ b/tests/aniso.c
@@ -66,6 +66,9 @@ int main(int argc, char *argv[])
const char *exts = (const char *)glGetString(GL_EXTENSIONS);
assert(hasext(exts, "GL_EXT_texture_filter_anisotropic"));
+ const char *vendor = (const char *)glGetString(GL_VENDOR);
+ printf("vendor: %s\n", vendor);
+
GLint aniso;
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso);
printf("Max anisotropy: %d (using that)\n", aniso);
diff --git a/tests/test_browser.py b/tests/test_browser.py
index be23074a..2ff9106b 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -869,6 +869,48 @@ keydown(100);keyup(100); // trigger the end
def test_glut_wheelevents(self):
self.btest('glut_wheelevents.c', '1')
+ def test_webgl_context_attributes(self):
+ # Javascript code to check the attributes support we want to test in the WebGL implementation
+ # (request the attribute, create a context and check its value afterwards in the context attributes).
+ # Tests will succeed when an attribute is not supported.
+ open(os.path.join(self.get_dir(), 'check_webgl_attributes_support.js'), 'w').write('''
+ mergeInto(LibraryManager.library, {
+ webglAntialiasSupported: function() {
+ canvas = document.createElement('canvas');
+ context = canvas.getContext('experimental-webgl', {antialias: true});
+ attributes = context.getContextAttributes();
+ return attributes.antialias;
+ },
+ webglDepthSupported: function() {
+ canvas = document.createElement('canvas');
+ context = canvas.getContext('experimental-webgl', {depth: true});
+ attributes = context.getContextAttributes();
+ return attributes.depth;
+ },
+ webglStencilSupported: function() {
+ canvas = document.createElement('canvas');
+ context = canvas.getContext('experimental-webgl', {stencil: true});
+ attributes = context.getContextAttributes();
+ return attributes.stencil;
+ }
+ });
+ ''')
+
+ # Copy common code file to temporary directory
+ filepath = path_from_root('tests/test_webgl_context_attributes_common.c')
+ temp_filepath = os.path.join(self.get_dir(), os.path.basename(filepath))
+ shutil.copyfile(filepath, temp_filepath)
+
+ # perform tests with attributes activated
+ self.btest('test_webgl_context_attributes_glut.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED'])
+ self.btest('test_webgl_context_attributes_sdl.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED'])
+ self.btest('test_webgl_context_attributes_glfw.c', '1', args=['--js-library', 'check_webgl_attributes_support.js', '-DAA_ACTIVATED', '-DDEPTH_ACTIVATED', '-DSTENCIL_ACTIVATED'])
+
+ # perform tests with attributes desactivated
+ self.btest('test_webgl_context_attributes_glut.c', '1', args=['--js-library', 'check_webgl_attributes_support.js'])
+ self.btest('test_webgl_context_attributes_sdl.c', '1', args=['--js-library', 'check_webgl_attributes_support.js'])
+ self.btest('test_webgl_context_attributes_glfw.c', '1', args=['--js-library', 'check_webgl_attributes_support.js'])
+
def test_emscripten_get_now(self):
self.btest('emscripten_get_now.cpp', '1')
diff --git a/tests/test_webgl_context_attributes_common.c b/tests/test_webgl_context_attributes_common.c
new file mode 100644
index 00000000..7131203b
--- /dev/null
+++ b/tests/test_webgl_context_attributes_common.c
@@ -0,0 +1,262 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <emscripten.h>
+
+#define BUFFER_OFFSET(i) ((char *)NULL + (i))
+
+static const int WINDOWS_SIZE = 500;
+
+static GLfloat vertices[] = { 0.0f, 250.f, 0.0f,
+ -250.f, -250.f, 0.0f,
+ 250.f, -250.f, 0.0f };
+
+static GLfloat vertices2[] = { 0.0f, 250.f, -1.0f,
+ -250.f, -250.f, -1.0f,
+ 250.f, -250.f, -1.0f };
+
+static GLuint shaderProgram = 0;
+static GLuint verticesVBO = 0;
+static GLuint verticesVBO2 = 0;
+
+static unsigned char backgroundColor[4] = {255, 255, 255, 255};
+static unsigned char triangleColor[4] = {255, 0, 0, 255};
+static unsigned char triangleColor2[4] = {0, 255, 0, 255};
+
+static char vertexShaderSrc[] =
+ "precision highp float;"
+ "precision highp int;"
+
+ "uniform mat4 u_mvpMatrix;"
+ "uniform vec4 u_color;"
+
+ "attribute vec3 a_position;"
+
+ "varying vec4 v_color;"
+
+ "void main() {"
+ " gl_Position = u_mvpMatrix * vec4(a_position, 1.0);"
+ " v_color = u_color;"
+ "}"
+ ;
+
+static char fragmentShaderSrc[] =
+ "precision highp float;"
+ "precision highp int;"
+
+ "varying vec4 v_color;"
+
+ "void main() {"
+ " gl_FragColor = v_color;"
+ "}"
+ ;
+
+static GLuint createShader(const char *source, int type) {
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 1, (const GLchar**)(&source), NULL);
+ glCompileShader(shader);
+ return shader;
+}
+
+static GLuint createShaderProgram(const char *vertexShaderSrc, const char *fragmentShaderSrc) {
+ GLuint program = glCreateProgram();
+ glAttachShader(program, createShader(vertexShaderSrc, GL_VERTEX_SHADER));
+ glAttachShader(program, createShader(fragmentShaderSrc, GL_FRAGMENT_SHADER));
+ glLinkProgram(program);
+ return program;
+}
+
+void ortho(float left, float right, float bottom, float top, float nearVal, float farVal, GLfloat *projMatrix) {
+ float tx = -(right+left)/(right-left);
+ float ty = -(top+bottom)/(top-bottom);
+ float tz = -(farVal+nearVal)/(farVal-nearVal);
+ memset(projMatrix, 0, 16 * sizeof(GLfloat));
+ projMatrix[0] = 2.0f / (right-left);
+ projMatrix[3] = tx;
+ projMatrix[1*4+1] = 2.0f / (top-bottom);
+ projMatrix[1*4+3] = ty;
+ projMatrix[2*4+2] = -2.0f / (farVal-nearVal);
+ projMatrix[2*4+3] = tz;
+ projMatrix[3*4+3] = 1.0f;
+}
+
+static void initGlObjects() {
+ glGenBuffers(1, &verticesVBO);
+ glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
+ glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), vertices, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glGenBuffers(1, &verticesVBO2);
+ glBindBuffer(GL_ARRAY_BUFFER, verticesVBO2);
+ glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), vertices2, GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ shaderProgram = createShaderProgram(vertexShaderSrc, fragmentShaderSrc);
+}
+
+static void drawTriangle(GLuint verticesVBO, unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
+ glUseProgram(shaderProgram);
+ GLuint posLoc = glGetAttribLocation(shaderProgram, "a_position");
+ GLuint mvpLoc = glGetUniformLocation(shaderProgram, "u_mvpMatrix");
+ GLuint colorLoc = glGetUniformLocation(shaderProgram, "u_color");
+
+ GLfloat mvpMat[16];
+ ortho(-WINDOWS_SIZE/2, WINDOWS_SIZE/2, -WINDOWS_SIZE/2, WINDOWS_SIZE/2, -100, 100, mvpMat);
+
+ glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, mvpMat);
+ glUniform4f(colorLoc, r/255.f, g/255.f, b/255.f, a/255.f);
+
+ glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
+ glEnableVertexAttribArray(posLoc);
+ glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), BUFFER_OFFSET(0));
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glUseProgram(0);
+}
+
+// Draw a red triangle on a white background. If antialiasing is disabled, resulting pixels
+// will only have white and red colors. If antialiasing is enabled, there will be pixels
+// whose color is different from red and white.
+static int testAntiAliasing(bool activated) {
+ glViewport(0, 0, WINDOWS_SIZE, WINDOWS_SIZE);
+ glClearColor(backgroundColor[0]/255.f, backgroundColor[1]/255.f, backgroundColor[2]/255.f, backgroundColor[3]/255.f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ drawTriangle(verticesVBO, triangleColor[0], triangleColor[1], triangleColor[2], triangleColor[3]);
+
+ bool antialiased = false;
+
+ unsigned char buffer[(WINDOWS_SIZE*WINDOWS_SIZE)*4];
+ glReadPixels(0, 0, WINDOWS_SIZE, WINDOWS_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, &buffer[0]);
+ glFinish();
+ for (unsigned int i = 0 ; i < WINDOWS_SIZE ; ++i) {
+ for (unsigned int j = 0 ; j < WINDOWS_SIZE ; ++j) {
+ unsigned char r = buffer[4*(i*WINDOWS_SIZE+j)];
+ unsigned char g = buffer[4*(i*WINDOWS_SIZE+j)+1];
+ unsigned char b = buffer[4*(i*WINDOWS_SIZE+j)+2];
+ unsigned char a = buffer[4*(i*WINDOWS_SIZE+j)+3];
+ if ((r == backgroundColor[0] && g == backgroundColor[1] && b == backgroundColor[2] && a == backgroundColor[3]) ||
+ (r == triangleColor[0] && g == triangleColor[1] && b == triangleColor[2] && a == triangleColor[3])) {
+ continue;
+ } else {
+ antialiased = true;
+ break;
+ }
+ }
+ }
+
+ return (activated && antialiased) || (!activated && !antialiased);
+}
+
+// Draw a red triangle with depth equals to 0 then a green triangle whose depth equals -1.
+// If there is an attached depth buffer, the resulting image will be a red triangle. If not,
+// the resulting image will be a green triangle.
+static int testDepth(bool activated) {
+ glViewport(0, 0, WINDOWS_SIZE, WINDOWS_SIZE);
+ glClearColor(backgroundColor[0]/255.f, backgroundColor[1]/255.f, backgroundColor[2]/255.f, backgroundColor[3]/255.f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+
+ drawTriangle(verticesVBO, triangleColor[0], triangleColor[1], triangleColor[2], triangleColor[3]);
+ drawTriangle(verticesVBO2, triangleColor2[0], triangleColor2[1], triangleColor2[2], triangleColor2[3]);
+
+ glDisable(GL_DEPTH_TEST);
+
+ // read the pixel at the center of the resulting image.
+ unsigned char buffer[4];
+ glReadPixels(WINDOWS_SIZE/2, WINDOWS_SIZE/2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &buffer[0]);
+
+ bool frontTriangleColor = (buffer[0] == triangleColor[0] && buffer[1] == triangleColor[1] &&
+ buffer[2] == triangleColor[2] && buffer[3] == triangleColor[3]);
+
+ bool backTriangleColor = (buffer[0] == triangleColor2[0] && buffer[1] == triangleColor2[1] &&
+ buffer[2] == triangleColor2[2] && buffer[3] == triangleColor2[3]);
+
+ return (activated && frontTriangleColor) || (!activated && backTriangleColor);
+}
+
+// The stencil function is set to GL_LEQUAL so fragments will be written to the
+// back buffer only if the ref value is less or equal than the one in the stencil buffer.
+// The content of the stencil buffer is initialized to 0xFF.
+// First draw a red triangle whose stencil ref value is 0x1.
+// Then draw a green triangle whose stencil ref value is 0xFF.
+// If there is an attached stencil buffer, the resulting image will be a red triangle. If not,
+// the resulting image will be a green triangle.
+static int testStencil(bool activated) {
+ glViewport(0, 0, WINDOWS_SIZE, WINDOWS_SIZE);
+ glClearColor(backgroundColor[0]/255.f, backgroundColor[1]/255.f, backgroundColor[2]/255.f, backgroundColor[3]/255.f);
+ glClearStencil(0xFF);
+ glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
+ glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+ glEnable(GL_STENCIL_TEST);
+
+ glStencilFunc(GL_LEQUAL, 0x1, 0xFF);
+ drawTriangle(verticesVBO, triangleColor[0], triangleColor[1], triangleColor[2], triangleColor[3]);
+
+ glStencilFunc(GL_LEQUAL, 0xFF, 0xFF);
+ drawTriangle(verticesVBO, triangleColor2[0], triangleColor2[1], triangleColor2[2], triangleColor2[3]);
+
+ glDisable(GL_STENCIL_TEST);
+
+ unsigned char buffer[4];
+ glReadPixels(WINDOWS_SIZE/2, WINDOWS_SIZE/2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &buffer[0]);
+
+ bool firstTriangleColor = (buffer[0] == triangleColor[0] && buffer[1] == triangleColor[1] &&
+ buffer[2] == triangleColor[2] && buffer[3] == triangleColor[3]);
+
+ bool secondTriangleColor = (buffer[0] == triangleColor2[0] && buffer[1] == triangleColor2[1] &&
+ buffer[2] == triangleColor2[2] && buffer[3] == triangleColor2[3]);
+
+ return (activated && firstTriangleColor) || (!activated && secondTriangleColor);
+}
+
+static bool antiAliasingActivated = false;
+static bool depthActivated = false;
+static bool stencilActivated = false;
+
+static int result = 0;
+static int resultAA = 0;
+static int resultDepth = 0;
+static int resultStencil = 0;
+
+static void draw() {
+
+ if (!resultAA) resultAA = testAntiAliasing(antiAliasingActivated);
+
+ if (!resultDepth) resultDepth = testDepth(depthActivated);
+
+ if (!resultStencil) resultStencil = testStencil(stencilActivated);
+
+ result = resultAA && resultDepth && resultStencil;
+
+}
+
+extern int webglAntialiasSupported();
+extern int webglDepthSupported();
+extern int webglStencilSupported();
+
+// Check attributes support in the WebGL implementation (see test_webgl_context_attributes function in test_browser.py)
+// Tests will succeed if they are not.
+static void checkContextAttributesSupport() {
+ if (!webglAntialiasSupported()) {
+ resultAA = 1;
+ EM_ASM(alert('warning: no antialiasing\n'));
+ }
+ if (!webglDepthSupported()) {
+ resultDepth = 1;
+ EM_ASM(alert('warning: no depth\n'));
+ }
+ if (!webglStencilSupported()) {
+ resultStencil = 1;
+ EM_ASM(alert('warning: no stencil\n'));
+ }
+}
+
+
diff --git a/tests/test_webgl_context_attributes_glfw.c b/tests/test_webgl_context_attributes_glfw.c
new file mode 100644
index 00000000..694236d0
--- /dev/null
+++ b/tests/test_webgl_context_attributes_glfw.c
@@ -0,0 +1,47 @@
+#include <GL/glew.h>
+#include <GL/glfw.h>
+#include <emscripten.h>
+
+#include "test_webgl_context_attributes_common.c"
+
+int nbSamples = 0;
+int nbDepthBits = 0;
+int nbStencilBits = 0;
+
+int main() {
+
+ checkContextAttributesSupport();
+
+ glfwInit();
+
+#ifdef AA_ACTIVATED
+ antiAliasingActivated = true;
+ nbSamples = 4;
+#endif
+
+#ifdef DEPTH_ACTIVATED
+ depthActivated = true;
+ nbDepthBits = 16;
+#endif
+
+#ifdef STENCIL_ACTIVATED
+ stencilActivated = true;
+ nbStencilBits = 8;
+#endif
+
+ glfwOpenWindowHint(GLFW_FSAA_SAMPLES, nbSamples);
+ glfwOpenWindow(WINDOWS_SIZE, WINDOWS_SIZE, 8, 8, 8, 8, nbDepthBits, nbStencilBits, GLFW_WINDOW);
+
+ glewInit();
+ initGlObjects();
+
+ draw();
+
+ glfwTerminate();
+
+ REPORT_RESULT();
+
+ return 0;
+
+}
+ \ No newline at end of file
diff --git a/tests/test_webgl_context_attributes_glut.c b/tests/test_webgl_context_attributes_glut.c
new file mode 100644
index 00000000..3255fc9a
--- /dev/null
+++ b/tests/test_webgl_context_attributes_glut.c
@@ -0,0 +1,42 @@
+#include <GL/glew.h>
+#include <GL/glut.h>
+#include <emscripten.h>
+
+#include "test_webgl_context_attributes_common.c"
+
+int main(int argc, char *argv[]) {
+
+ checkContextAttributesSupport();
+
+ unsigned int glutDisplayMode = GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA;
+
+#ifdef AA_ACTIVATED
+ antiAliasingActivated = true;
+ glutDisplayMode |= GLUT_MULTISAMPLE;
+#endif
+
+#ifdef DEPTH_ACTIVATED
+ depthActivated = true;
+ glutDisplayMode |= GLUT_DEPTH;
+#endif
+
+#ifdef STENCIL_ACTIVATED
+ stencilActivated = true;
+ glutDisplayMode |= GLUT_STENCIL;
+#endif
+
+ glutInit(&argc, argv);
+ glutInitWindowSize(WINDOWS_SIZE, WINDOWS_SIZE);
+ glutInitDisplayMode(glutDisplayMode);
+ glutCreateWindow("WebGL");
+ glutDisplayFunc(draw);
+
+ glewInit();
+ initGlObjects();
+
+ draw();
+
+ REPORT_RESULT();
+
+ return 0;
+}
diff --git a/tests/test_webgl_context_attributes_sdl.c b/tests/test_webgl_context_attributes_sdl.c
new file mode 100644
index 00000000..23ad4378
--- /dev/null
+++ b/tests/test_webgl_context_attributes_sdl.c
@@ -0,0 +1,50 @@
+#include <GL/glew.h>
+#define NO_SDL_GLEXT
+#include <SDL/SDL.h>
+#include <SDL/SDL_opengl.h>
+#include <emscripten.h>
+
+#include "test_webgl_context_attributes_common.c"
+
+int main(int argc, char *argv[]) {
+
+ checkContextAttributesSupport();
+
+ SDL_Init(SDL_INIT_VIDEO);
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+#ifdef AA_ACTIVATED
+ antiAliasingActivated = true;
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
+#else
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
+#endif
+
+#ifdef DEPTH_ACTIVATED
+ depthActivated = true;
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+#else
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
+#endif
+
+#ifdef STENCIL_ACTIVATED
+ stencilActivated = true;
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+#else
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0);
+#endif
+
+ SDL_Surface *screen = SDL_SetVideoMode(WINDOWS_SIZE, WINDOWS_SIZE, 32, SDL_OPENGL);
+
+ glewInit();
+ initGlObjects();
+
+ draw();
+
+ REPORT_RESULT();
+
+ return 0;
+}
diff --git a/tools/file_packager.py b/tools/file_packager.py
index a2349a57..1d0ec447 100644
--- a/tools/file_packager.py
+++ b/tools/file_packager.py
@@ -134,6 +134,11 @@ if (not force) and len(data_files) == 0:
ret = '''
var Module;
if (typeof Module === 'undefined') Module = eval('(function() { try { return Module || {} } catch(e) { return {} } })()');
+if (!Module.expectedDataFileDownloads) {
+ Module.expectedDataFileDownloads = 0;
+ Module.finishedDataFileDownloads = 0;
+}
+Module.expectedDataFileDownloads++;
(function() {
'''
@@ -338,18 +343,9 @@ if has_preloaded:
send: function() {},
onload: function() {
var byteArray = this.byteArray.subarray(this.start, this.end);
- if (this.crunched) {
- var ddsHeader = byteArray.subarray(0, 128);
- var that = this;
- requestDecrunch(this.name, byteArray.subarray(128), function(ddsData) {
- byteArray = new Uint8Array(ddsHeader.length + ddsData.length);
- byteArray.set(ddsHeader, 0);
- byteArray.set(ddsData, 128);
- that.finish(byteArray);
- });
- } else {
+%s
this.finish(byteArray);
- }
+%s
},
finish: function(byteArray) {
var that = this;
@@ -365,7 +361,20 @@ if has_preloaded:
this.requests[this.name] = null;
},
};
- '''
+ ''' % ('' if not crunch else '''
+ if (this.crunched) {
+ var ddsHeader = byteArray.subarray(0, 128);
+ var that = this;
+ requestDecrunch(this.name, byteArray.subarray(128), function(ddsData) {
+ byteArray = new Uint8Array(ddsHeader.length + ddsData.length);
+ byteArray.set(ddsHeader, 0);
+ byteArray.set(ddsData, 128);
+ that.finish(byteArray);
+ });
+ } else {
+''', '' if not crunch else '''
+ }
+''')
counter = 0
for file_ in data_files:
@@ -427,12 +436,6 @@ if has_preloaded:
package_uuid = uuid.uuid4();
remote_package_name = os.path.basename(Compression.compressed_name(data_target) if Compression.on else data_target)
code += r'''
- if (!Module.expectedDataFileDownloads) {
- Module.expectedDataFileDownloads = 0;
- Module.finishedDataFileDownloads = 0;
- }
- Module.expectedDataFileDownloads++;
-
var PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/');
var PACKAGE_NAME = '%s';
var REMOTE_PACKAGE_NAME = '%s';