aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/library.js4
-rw-r--r--src/library_browser.js6
-rw-r--r--src/library_gl.js70
-rw-r--r--src/library_sdl.js196
4 files changed, 202 insertions, 74 deletions
diff --git a/src/library.js b/src/library.js
index b7973d98..3597891e 100644
--- a/src/library.js
+++ b/src/library.js
@@ -867,10 +867,6 @@ LibraryManager.library = {
}
var file = FS.findObject(Pointer_stringify(path));
if (file === null) return -1;
- if (!file.write) {
- ___setErrNo(ERRNO_CODES.EPERM);
- return -1;
- }
file.timestamp = time;
return 0;
},
diff --git a/src/library_browser.js b/src/library_browser.js
index d9fd3ee5..7f79b2bd 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -84,13 +84,17 @@ mergeInto(LibraryManager.library, {
var imagePlugin = {};
imagePlugin['canHandle'] = function(name) {
- return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/.exec(name);
+ return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name);
};
imagePlugin['handle'] = function(byteArray, name, onload, onerror) {
var b = null;
if (Browser.hasBlobConstructor) {
try {
b = new Blob([byteArray], { type: getMimetype(name) });
+ if (b.size !== byteArray.length) { // Safari bug #118630
+ // Safari's Blob can only take an ArrayBuffer
+ b = new Blob([(new Uint8Array(byteArray)).buffer], { type: getMimetype(name) });
+ }
} catch(e) {
Runtime.warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder');
}
diff --git a/src/library_gl.js b/src/library_gl.js
index e59492cf..959773bc 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -122,14 +122,6 @@ var LibraryGL = {
}
},
- // Linear lookup in one of the tables (buffers, programs, etc.). TODO: consider using a weakmap to make this faster, if it matters
- scan: function(table, object) {
- for (var item in table) {
- if (table[item] == object) return item;
- }
- return 0;
- },
-
// Find a token in a shader source string
findToken: function(source, token) {
function isIdentChar(ch) {
@@ -402,15 +394,15 @@ var LibraryGL = {
{{{ makeSetValue('p', 'i*4', 'result[i]', 'i32') }}};
}
} else if (result instanceof WebGLBuffer) {
- {{{ makeSetValue('p', '0', 'GL.scan(GL.buffers, result)', 'i32') }}};
+ {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}};
} else if (result instanceof WebGLProgram) {
- {{{ makeSetValue('p', '0', 'GL.scan(GL.programs, result)', 'i32') }}};
+ {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}};
} else if (result instanceof WebGLFramebuffer) {
- {{{ makeSetValue('p', '0', 'GL.scan(GL.framebuffers, result)', 'i32') }}};
+ {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}};
} else if (result instanceof WebGLRenderbuffer) {
- {{{ makeSetValue('p', '0', 'GL.scan(GL.renderbuffers, result)', 'i32') }}};
+ {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}};
} else if (result instanceof WebGLTexture) {
- {{{ makeSetValue('p', '0', 'GL.scan(GL.textures, result)', 'i32') }}};
+ {{{ makeSetValue('p', '0', 'result.name | 0', 'i32') }}};
} else {
throw 'Unknown object returned from WebGL getParameter';
}
@@ -445,15 +437,15 @@ var LibraryGL = {
{{{ makeSetValue('p', 'i*4', 'result[i]', 'float') }}};
}
} else if (result instanceof WebGLBuffer) {
- {{{ makeSetValue('p', '0', 'GL.scan(GL.buffers, result)', 'float') }}};
+ {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}};
} else if (result instanceof WebGLProgram) {
- {{{ makeSetValue('p', '0', 'GL.scan(GL.programs, result)', 'float') }}};
+ {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}};
} else if (result instanceof WebGLFramebuffer) {
- {{{ makeSetValue('p', '0', 'GL.scan(GL.framebuffers, result)', 'float') }}};
+ {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}};
} else if (result instanceof WebGLRenderbuffer) {
- {{{ makeSetValue('p', '0', 'GL.scan(GL.renderbuffers, result)', 'float') }}};
+ {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}};
} else if (result instanceof WebGLTexture) {
- {{{ makeSetValue('p', '0', 'GL.scan(GL.textures, result)', 'float') }}};
+ {{{ makeSetValue('p', '0', 'result.name | 0', 'float') }}};
} else {
throw 'Unknown object returned from WebGL getParameter';
}
@@ -508,7 +500,9 @@ var LibraryGL = {
glGenTextures: function(n, textures) {
for (var i = 0; i < n; i++) {
var id = GL.getNewId(GL.textures);
- GL.textures[id] = Module.ctx.createTexture();
+ var texture = Module.ctx.createTexture();
+ texture.name = id;
+ GL.textures[id] = texture;
{{{ makeSetValue('textures', 'i*4', 'id', 'i32') }}};
}
},
@@ -517,7 +511,9 @@ var LibraryGL = {
glDeleteTextures: function(n, textures) {
for (var i = 0; i < n; i++) {
var id = {{{ makeGetValue('textures', 'i*4', 'i32') }}};
- Module.ctx.deleteTexture(GL.textures[id]);
+ var texture = GL.textures[id];
+ Module.ctx.deleteTexture(texture);
+ texture.name = 0;
GL.textures[id] = null;
}
},
@@ -622,7 +618,9 @@ var LibraryGL = {
glGenBuffers: function(n, buffers) {
for (var i = 0; i < n; i++) {
var id = GL.getNewId(GL.buffers);
- GL.buffers[id] = Module.ctx.createBuffer();
+ var buffer = Module.ctx.createBuffer();
+ buffer.name = id;
+ GL.buffers[id] = buffer;
{{{ makeSetValue('buffers', 'i*4', 'id', 'i32') }}};
}
},
@@ -631,7 +629,9 @@ var LibraryGL = {
glDeleteBuffers: function(n, buffers) {
for (var i = 0; i < n; i++) {
var id = {{{ makeGetValue('buffers', 'i*4', 'i32') }}};
- Module.ctx.deleteBuffer(GL.buffers[id]);
+ var buffer = GL.buffers[id];
+ Module.ctx.deleteBuffer(buffer);
+ buffer.name = 0;
GL.buffers[id] = null;
if (id == GL.currArrayBuffer) GL.currArrayBuffer = 0;
@@ -665,7 +665,9 @@ var LibraryGL = {
glGenRenderbuffers: function(n, renderbuffers) {
for (var i = 0; i < n; i++) {
var id = GL.getNewId(GL.renderbuffers);
- GL.renderbuffers[id] = Module.ctx.createRenderbuffer();
+ var renderbuffer = Module.ctx.createRenderbuffer();
+ renderbuffer.name = id;
+ GL.renderbuffers[id] = renderbuffer;
{{{ makeSetValue('renderbuffers', 'i*4', 'id', 'i32') }}};
}
},
@@ -674,8 +676,10 @@ var LibraryGL = {
glDeleteRenderbuffers: function(n, renderbuffers) {
for (var i = 0; i < n; i++) {
var id = {{{ makeGetValue('renderbuffers', 'i*4', 'i32') }}};
- Module.ctx.deleteRenderbuffer(GL.renderbuffers[id]);
- GL.renderbuffers[id];
+ var renderbuffer = GL.renderbuffers[id];
+ Module.ctx.deleteRenderbuffer(renderbuffer);
+ renderbuffer.name = 0;
+ GL.renderbuffers[id] = null;
}
},
@@ -1139,13 +1143,17 @@ var LibraryGL = {
glCreateProgram__sig: 'i',
glCreateProgram: function() {
var id = GL.getNewId(GL.programs);
- GL.programs[id] = Module.ctx.createProgram();
+ var program = Module.ctx.createProgram();
+ program.name = id;
+ GL.programs[id] = program;
return id;
},
glDeleteProgram__sig: 'vi',
glDeleteProgram: function(program) {
- Module.ctx.deleteProgram(GL.programs[program]);
+ var program = GL.programs[program];
+ Module.ctx.deleteProgram(program);
+ program.name = 0;
GL.programs[program] = null;
GL.uniformTable[program] = null;
},
@@ -1221,7 +1229,9 @@ var LibraryGL = {
glGenFramebuffers: function(n, ids) {
for (var i = 0; i < n; ++i) {
var id = GL.getNewId(GL.framebuffers);
- GL.framebuffers[id] = Module.ctx.createFramebuffer();
+ var framebuffer = Module.ctx.createFramebuffer();
+ framebuffer.name = id;
+ GL.framebuffers[id] = framebuffer;
{{{ makeSetValue('ids', 'i*4', 'id', 'i32') }}};
}
},
@@ -1230,7 +1240,9 @@ var LibraryGL = {
glDeleteFramebuffers: function(n, framebuffers) {
for (var i = 0; i < n; ++i) {
var id = {{{ makeGetValue('framebuffers', 'i*4', 'i32') }}};
- Module.ctx.deleteFramebuffer(GL.framebuffers[id]);
+ var framebuffer = GL.framebuffers[id];
+ Module.ctx.deleteFramebuffer(framebuffer);
+ framebuffer.name = 0;
GL.framebuffers[id] = null;
}
},
diff --git a/src/library_sdl.js b/src/library_sdl.js
index af71da26..b7d73862 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -21,6 +21,8 @@ var LibrarySDL = {
version: null,
surfaces: {},
+ // A pool of freed canvas elements. Reusing them avoids GC pauses.
+ canvasPool: [],
events: [],
fonts: [null],
@@ -246,7 +248,7 @@ var LibrarySDL = {
},
translateRGBAToCSSRGBA: function(r, g, b, a) {
- return 'rgba(' + r + ',' + g + ',' + b + ',' + (a/255) + ')';
+ return 'rgba(' + (r&0xff) + ',' + (g&0xff) + ',' + (b&0xff) + ',' + (a&0xff)/255 + ')';
},
translateRGBAToColor: function(r, g, b, a) {
@@ -288,7 +290,11 @@ var LibrarySDL = {
SDL.GL = SDL.GL || useWebGL;
var canvas;
if (!usePageCanvas) {
- canvas = document.createElement('canvas');
+ if (SDL.canvasPool.length > 0) {
+ canvas = SDL.canvasPool.pop();
+ } else {
+ canvas = document.createElement('canvas');
+ }
canvas.width = width;
canvas.height = height;
} else {
@@ -355,8 +361,10 @@ var LibrarySDL = {
},
freeSurface: function(surf) {
- _free(SDL.surfaces[surf].buffer);
- _free(SDL.surfaces[surf].pixelFormat);
+ var info = SDL.surfaces[surf];
+ if (!info.usePageCanvas && info.canvas) SDL.canvasPool.push(info.canvas);
+ _free(info.buffer);
+ _free(info.pixelFormat);
_free(surf);
SDL.surfaces[surf] = null;
},
@@ -1062,6 +1070,7 @@ var LibrarySDL = {
surfData.ctx.fillStyle = SDL.translateColorToCSSRGBA(color);
surfData.ctx.fillRect(r.x, r.y, r.w, r.h);
surfData.ctx.restore();
+ return 0;
},
SDL_BlitSurface__deps: ['SDL_UpperBlit'],
@@ -1071,11 +1080,19 @@ var LibrarySDL = {
zoomSurface: function(src, x, y, smooth) {
var srcData = SDL.surfaces[src];
- var w = srcData.width*x;
- var h = srcData.height*y;
- var ret = SDL.makeSurface(w, h, srcData.flags, false, 'zoomSurface');
+ var w = srcData.width * x;
+ var h = srcData.height * y;
+ var ret = SDL.makeSurface(Math.abs(w), Math.abs(h), srcData.flags, false, 'zoomSurface');
var dstData = SDL.surfaces[ret];
- dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h);
+ if (x >= 0 && y >= 0) dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h);
+ else {
+ dstData.ctx.save();
+ dstData.ctx.scale(x < 0 ? -1 : 1, y < 0 ? -1 : 1);
+ dstData.ctx.drawImage(srcData.canvas, w < 0 ? w : 0, h < 0 ? h : 0, Math.abs(w), Math.abs(h));
+ // XXX I think this should work according to the spec, but currently
+ // fails on FF: dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h);
+ dstData.ctx.restore();
+ }
return ret;
},
@@ -1096,6 +1113,14 @@ var LibrarySDL = {
SDL.surfaces[surf].alpha = alpha;
},
+ SDL_SetColorKey: function(surf, flag, key) {
+ // SetColorKey assigns one color to be rendered as transparent. I don't
+ // think the canvas API allows for anything like this, and iterating through
+ // each pixel to replace that color seems prohibitively expensive.
+ Runtime.warnOnce('SDL_SetColorKey is a no-op for performance reasons');
+ return 0;
+ },
+
SDL_GetTicks: function() {
return Math.floor(Date.now() - SDL.startTime);
},
@@ -1512,15 +1537,20 @@ var LibrarySDL = {
},
Mix_HaltChannel: function(channel) {
- var info = SDL.channels[channel];
- if (info.audio) {
- info.audio.pause();
- info.audio = null;
- } else {
- Module.printErr('No Audio for channel: ' + channel);
+ function halt(channel) {
+ var info = SDL.channels[channel];
+ if (info.audio) {
+ info.audio.pause();
+ info.audio = null;
+ }
+ if (SDL.channelFinished) {
+ Runtime.getFuncWrapper(SDL.channelFinished, 'vi')(channel);
+ }
}
- if (SDL.channelFinished) {
- Runtime.getFuncWrapper(SDL.channelFinished, 'vi')(channel);
+ if (channel != -1) {
+ halt(channel);
+ } else {
+ for (var i = 0; i < SDL.channels.length; ++i) halt(i);
}
return 0;
},
@@ -1707,6 +1737,7 @@ var LibrarySDL = {
},
TTF_RenderText_Blended: 'TTF_RenderText_Solid', // XXX ignore blending vs. solid
TTF_RenderText_Shaded: 'TTF_RenderText_Solid', // XXX ignore blending vs. solid
+ TTF_RenderUTF8_Solid: 'TTF_RenderText_Solid',
TTF_SizeText: function(font, text, w, h) {
var fontData = SDL.fonts[font];
@@ -1731,35 +1762,114 @@ var LibrarySDL = {
// SDL gfx
+ $SDL_gfx: {
+ drawRectangle: function(surf, x1, y1, x2, y2, action, cssColor) {
+ x1 = x1 << 16 >> 16;
+ y1 = y1 << 16 >> 16;
+ x2 = x2 << 16 >> 16;
+ y2 = y2 << 16 >> 16;
+ var surfData = SDL.surfaces[surf];
+ assert(!surfData.locked); // but we could unlock and re-lock if we must..
+ // TODO: if ctx does not change, leave as is, and also do not re-set xStyle etc.
+ var x = x1 < x2 ? x1 : x2;
+ var y = y1 < y2 ? y1 : y2;
+ var w = Math.abs(x2 - x1);
+ var h = Math.abs(y2 - y1);
+ surfData.ctx.save();
+ surfData.ctx[action + 'Style'] = cssColor;
+ surfData.ctx[action + 'Rect'](x, y, w, h);
+ surfData.ctx.restore();
+ },
+ drawLine: function(surf, x1, y1, x2, y2, cssColor) {
+ x1 = x1 << 16 >> 16;
+ y1 = y1 << 16 >> 16;
+ x2 = x2 << 16 >> 16;
+ y2 = y2 << 16 >> 16;
+ var surfData = SDL.surfaces[surf];
+ assert(!surfData.locked); // but we could unlock and re-lock if we must..
+ surfData.ctx.save();
+ surfData.ctx.strokeStyle = cssColor;
+ surfData.ctx.beginPath();
+ surfData.ctx.moveTo(x1, y1);
+ surfData.ctx.lineTo(x2, y2);
+ surfData.ctx.stroke();
+ surfData.ctx.restore();
+ },
+ // See http://stackoverflow.com/questions/2172798/how-to-draw-an-oval-in-html5-canvas
+ drawEllipse: function(surf, x, y, rx, ry, action, cssColor) {
+ x = x << 16 >> 16;
+ y = y << 16 >> 16;
+ rx = rx << 16 >> 16;
+ ry = ry << 16 >> 16;
+ var surfData = SDL.surfaces[surf];
+ assert(!surfData.locked); // but we could unlock and re-lock if we must..
+
+ surfData.ctx.save();
+ surfData.ctx.beginPath();
+ surfData.ctx.translate(x, y);
+ surfData.ctx.scale(rx, ry);
+ surfData.ctx.arc(0, 0, 1, 0, 2 * Math.PI);
+ surfData.ctx.restore();
+
+ surfData.ctx.save();
+ surfData.ctx[action + 'Style'] = cssColor;
+ surfData.ctx[action]();
+ surfData.ctx.restore();
+ },
+ // the gfx library uses something different from the rest of SDL...
+ translateColorToCSSRGBA: function(rgba) {
+ return 'rgba(' + (rgba>>>24) + ',' + (rgba>>16 & 0xff) + ',' + (rgba>>8 & 0xff) + ',' + (rgba&0xff) + ')';
+ }
+ },
+
+ boxColor__deps: ['$SDL_gfx'],
+ boxColor: function(surf, x1, y1, x2, y2, color) {
+ return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'fill', SDL_gfx.translateColorToCSSRGBA(color));
+ },
+
+ boxRGBA__deps: ['$SDL_gfx'],
boxRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) {
- var surfData = SDL.surfaces[surf];
- assert(!surfData.locked); // but we could unlock and re-lock if we must..
- // TODO: if ctx does not change, leave as is, and also do not re-set xStyle etc.
- surfData.ctx.save();
- surfData.ctx.fillStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a);
- surfData.ctx.fillRect(x1, y1, x2-x1, y2-y1);
- surfData.ctx.restore();
+ return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'fill', SDL.translateRGBAToCSSRGBA(r, g, b, a));
},
+ rectangleColor__deps: ['$SDL_gfx'],
+ rectangleColor: function(surf, x1, y1, x2, y2, color) {
+ return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'stroke', SDL_gfx.translateColorToCSSRGBA(color));
+ },
+
+ rectangleRGBA__deps: ['$SDL_gfx'],
rectangleRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) {
- var surfData = SDL.surfaces[surf];
- assert(!surfData.locked); // but we could unlock and re-lock if we must..
- surfData.ctx.save();
- surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a);
- surfData.ctx.strokeRect(x1, y1, x2-x1, y2-y1);
- surfData.ctx.restore();
+ return SDL_gfx.drawRectangle(surf, x1, y1, x2, y2, 'stroke', SDL.translateRGBAToCSSRGBA(r, g, b, a));
+ },
+
+ ellipseColor__deps: ['$SDL_gfx'],
+ ellipseColor: function(surf, x, y, rx, ry, color) {
+ return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'stroke', SDL_gfx.translateColorToCSSRGBA(color));
+ },
+
+ ellipseRGBA__deps: ['$SDL_gfx'],
+ ellipseRGBA: function(surf, x, y, rx, ry, r, g, b, a) {
+ return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'stroke', SDL.translateRGBAToCSSRGBA(r, g, b, a));
+ },
+
+ filledEllipseColor__deps: ['$SDL_gfx'],
+ filledEllipseColor: function(surf, x, y, rx, ry, color) {
+ return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'fill', SDL_gfx.translateColorToCSSRGBA(color));
+ },
+
+ filledEllipseRGBA__deps: ['$SDL_gfx'],
+ filledEllipseRGBA: function(surf, x, y, rx, ry, r, g, b, a) {
+ return SDL_gfx.drawEllipse(surf, x, y, rx, ry, 'fill', SDL.translateRGBAToCSSRGBA(r, g, b, a));
},
+ lineColor__deps: ['$SDL_gfx'],
+ lineColor: function(surf, x1, y1, x2, y2, color) {
+ return SDL_gfx.drawLine(surf, x1, y1, x2, y2, SDL_gfx.translateColorToCSSRGBA(color));
+ },
+
+ lineRGBA__deps: ['$SDL_gfx'],
lineRGBA: function(surf, x1, y1, x2, y2, r, g, b, a) {
- var surfData = SDL.surfaces[surf];
- assert(!surfData.locked); // but we could unlock and re-lock if we must..
- surfData.ctx.save();
- surfData.ctx.strokeStyle = SDL.translateRGBAToCSSRGBA(r, g, b, a);
- surfData.ctx.beginPath();
- surfData.ctx.moveTo(x1, y1);
- surfData.ctx.lineTo(x2, y2);
- surfData.ctx.stroke();
- surfData.ctx.restore();
+ return SDL_gfx.drawLine(surf, x1, y1, x2, y2, SDL.translateRGBAToCSSRGBA(r, g, b, a));
},
pixelRGBA__deps: ['boxRGBA'],
@@ -1845,12 +1955,18 @@ var LibrarySDL = {
return -1;
},
+ // Joysticks
+
+ SDL_NumJoysticks: function() { return 0 },
+
+ SDL_JoystickOpen: function(deviceIndex) { return 0 },
+
+ SDL_JoystickGetButton: function(joystick, button) { return 0 },
+
// Misc
SDL_InitSubSystem: function(flags) { return 0 },
- SDL_NumJoysticks: function() { return 0 },
-
SDL_RWFromFile: function(filename, mode) {
return filename; // XXX We just forward the filename
},