aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/library.js25
-rw-r--r--src/library_browser.js8
-rw-r--r--src/library_gl.js198
-rw-r--r--src/library_sdl.js73
-rw-r--r--src/parseTools.js2
-rw-r--r--src/shell.html7
6 files changed, 246 insertions, 67 deletions
diff --git a/src/library.js b/src/library.js
index 8d68251f..fe6ae0fb 100644
--- a/src/library.js
+++ b/src/library.js
@@ -3473,35 +3473,37 @@ LibraryManager.library = {
var chr;
var ret = 0;
- var legit = false;
// Get whole part.
+ var whole = false;
while(1) {
chr = {{{ makeGetValue('str', 0, 'i8') }}};
if (!_isdigit(chr)) break;
- legit = true;
+ whole = true;
ret = ret*10 + chr - '0'.charCodeAt(0);
str++;
}
- if (!legit) {
- {{{ makeSetValue('endptr', 0, 'origin', '*') }}}
- return 0;
- }
-
// Get fractional part.
+ var fraction = false;
if ({{{ makeGetValue('str', 0, 'i8') }}} == '.'.charCodeAt(0)) {
str++;
var mul = 1/10;
while(1) {
chr = {{{ makeGetValue('str', 0, 'i8') }}};
if (!_isdigit(chr)) break;
+ fraction = true;
ret += mul*(chr - '0'.charCodeAt(0));
mul /= 10;
str++;
}
}
+ if (!whole && !fraction) {
+ {{{ makeSetValue('endptr', 0, 'origin', '*') }}}
+ return 0;
+ }
+
// Get exponent part.
chr = {{{ makeGetValue('str', 0, 'i8') }}};
if (chr == 'e'.charCodeAt(0) || chr == 'E'.charCodeAt(0)) {
@@ -4759,6 +4761,15 @@ LibraryManager.library = {
// type_info for void*.
_ZTIPv: [0],
+ llvm_uadd_with_overflow_i16: function(x, y) {
+ x = (x>>>0) & 0xffff;
+ y = (y>>>0) & 0xffff;
+ return {
+ f0: (x+y) & 0xffff,
+ f1: x+y > 65535
+ };
+ },
+
llvm_uadd_with_overflow_i32: function(x, y) {
x = x>>>0;
y = y>>>0;
diff --git a/src/library_browser.js b/src/library_browser.js
index efb9e444..59d37336 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -39,11 +39,11 @@ mergeInto(LibraryManager.library, {
wrapper[prop] = function() {
if (GL.debug) {
var printArgs = Array.prototype.slice.call(arguments).map(Runtime.prettyPrint);
- console.log('[gl_f:' + prop + ':' + printArgs + ']');
+ Module.printErr('[gl_f:' + prop + ':' + printArgs + ']');
}
var ret = tempCtx[prop].apply(tempCtx, arguments);
if (GL.debug && typeof ret != 'undefined') {
- console.log('[ gl:' + prop + ':return:' + Runtime.prettyPrint(ret) + ']');
+ Module.printErr('[ gl:' + prop + ':return:' + Runtime.prettyPrint(ret) + ']');
}
return ret;
}
@@ -51,12 +51,12 @@ mergeInto(LibraryManager.library, {
}
case 'number': case 'string': {
wrapper.__defineGetter__(prop, function() {
- //console.log('[gl_g:' + prop + ':' + tempCtx[prop] + ']');
+ //Module.printErr('[gl_g:' + prop + ':' + tempCtx[prop] + ']');
return tempCtx[prop];
});
wrapper.__defineSetter__(prop, function(value) {
if (GL.debug) {
- console.log('[gl_s:' + prop + ':' + value + ']');
+ Module.printErr('[gl_s:' + prop + ':' + value + ']');
}
tempCtx[prop] = value;
});
diff --git a/src/library_gl.js b/src/library_gl.js
index 2be48ba1..578b8437 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -128,6 +128,14 @@ var LibraryGL = {
},
glGetIntegerv: function(name_, p) {
+ switch(name_) { // Handle a few trivial GLES values
+ case 0x8DFA: // GL_SHADER_COMPILER
+ {{{ makeSetValue('p', '0', '1', 'i32') }}};
+ return;
+ case 0x8DF9: // GL_NUM_SHADER_BINARY_FORMATS
+ {{{ makeSetValue('p', '0', '0', 'i32') }}};
+ return;
+ }
var result = Module.ctx.getParameter(name_);
switch (typeof(result)) {
case "number":
@@ -816,7 +824,7 @@ var LibraryGL = {
},
glUseProgram: function(program) {
- Module.ctx.useProgram(GL.programs[program]);
+ Module.ctx.useProgram(program ? GL.programs[program] : null);
},
glValidateProgram: function(program) {
@@ -930,6 +938,15 @@ var LibraryGL = {
glGetIntegerv(pname, params);
};
+ var glGetString = _glGetString;
+ _glGetString = function(name_) {
+ switch(name_) {
+ case 0x1F03 /* GL_EXTENSIONS */: // Add various extensions that we can support
+ return 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'), 'i8', ALLOC_NORMAL);
+ }
+ return glGetString(name_);
+ };
+
// Do some automatic rewriting to work around GLSL differences. Note that this must be done in
// tandem with the rest of the program, by itself it cannot suffice.
// Note that we need to remember shader types for this rewriting, saving sources makes it easier to debug.
@@ -969,6 +986,9 @@ var LibraryGL = {
source = source.replace(/gl_ProjectionMatrix/g, 'u_projection');
if (old != source) need_pm = 1;
old = source;
+ source = source.replace(/gl_ModelViewMatrixTranspose\[2\]/g, 'vec4(u_modelView[0][0], u_modelView[1][0], u_modelView[2][0], u_modelView[3][0])'); // XXX extremely inefficient
+ if (old != source) need_mm = 1;
+ old = source;
source = source.replace(/gl_ModelViewMatrix/g, 'u_modelView');
if (old != source) need_mm = 1;
old = source;
@@ -977,9 +997,6 @@ var LibraryGL = {
old = source;
source = source.replace(/gl_ModelViewProjectionMatrix/g, '(u_projection * u_modelView)');
if (old != source) need_pm = need_mm = 1;
- old = source;
- source = source.replace(/gl_ModelViewMatrixTranspose\[2\]/g, 'vec3(u_modelView[0][0], u_modelView[1][0], u_modelView[2][0])'); // XXX extremely inefficient
- if (old != source) need_mm = 1;
if (need_pv && !has_pv) source = 'attribute vec4 a_position; \n' + source;
if (need_mm && !has_mm) source = 'uniform mat4 u_modelView; \n' + source;
if (need_pm && !has_pm) source = 'uniform mat4 u_projection; \n' + source;
@@ -1045,14 +1062,14 @@ var LibraryGL = {
_glCompileShader = function(shader) {
Module.ctx.compileShader(GL.shaders[shader]);
if (!Module.ctx.getShaderParameter(GL.shaders[shader], Module.ctx.COMPILE_STATUS)) {
- console.log('Failed to compile shader: ' + Module.ctx.getShaderInfoLog(GL.shaders[shader]));
- console.log('Info: ' + JSON.stringify(GL.shaderInfos[shader]));
+ Module.printErr('Failed to compile shader: ' + Module.ctx.getShaderInfoLog(GL.shaders[shader]));
+ Module.printErr('Info: ' + JSON.stringify(GL.shaderInfos[shader]));
#if GL_DEBUG
- console.log('Original source: ' + GL.shaderOriginalSources[shader]);
- console.log('Source: ' + GL.shaderSources[shader]);
+ Module.printErr('Original source: ' + GL.shaderOriginalSources[shader]);
+ Module.printErr('Source: ' + GL.shaderSources[shader]);
throw 'Shader compilation halt';
#else
- console.log('Enable GL_DEBUG to see shader source');
+ Module.printErr('Enable GL_DEBUG to see shader source');
#endif
}
};
@@ -1069,11 +1086,13 @@ var LibraryGL = {
_glUseProgram = function(program) {
#if GL_DEBUG
if (GL.debug) {
- console.log('[using program with shaders:]');
- GL.programShaders[program].forEach(function(shader) {
- console.log(' shader ' + shader + ', original source: ' + GL.shaderOriginalSources[shader]);
- console.log(' Source: ' + GL.shaderSources[shader]);
- });
+ Module.printErr('[using program with shaders]');
+ if (program) {
+ GL.programShaders[program].forEach(function(shader) {
+ Module.printErr(' shader ' + shader + ', original source: ' + GL.shaderOriginalSources[shader]);
+ Module.printErr(' Source: ' + GL.shaderSources[shader]);
+ });
+ }
}
#endif
GL.currProgram = program;
@@ -1140,7 +1159,7 @@ var LibraryGL = {
} else if (GL.shaders[id]) {
_glDeleteShader(id);
} else {
- console.log('WARNING: deleteObject received invalid id: ' + id);
+ Module.printErr('WARNING: deleteObject received invalid id: ' + id);
}
}; break;
case 'glGetObjectParameteriv': func = function(id, type, result) {
@@ -1157,7 +1176,7 @@ var LibraryGL = {
}
_glGetShaderiv(id, type, result);
} else {
- console.log('WARNING: getObjectParameteriv received invalid id: ' + id);
+ Module.printErr('WARNING: getObjectParameteriv received invalid id: ' + id);
}
}; break;
case 'glGetInfoLog': func = function(id, maxLength, length, infoLog) {
@@ -1166,12 +1185,13 @@ var LibraryGL = {
} else if (GL.shaders[id]) {
_glGetShaderInfoLog(id, maxLength, length, infoLog);
} else {
- console.log('WARNING: getObjectParameteriv received invalid id: ' + id);
+ Module.printErr('WARNING: getObjectParameteriv received invalid id: ' + id);
}
}; break;
case 'glBindProgram': func = function(type, id) {
assert(id == 0);
}; break;
+ case 'glDrawRangeElements': func = _glDrawRangeElements; break;
case 'glShaderSource': func = _glShaderSource; break;
case 'glCompileShader': func = _glCompileShader; break;
case 'glLinkProgram': func = _glLinkProgram; break;
@@ -1220,9 +1240,9 @@ var LibraryGL = {
case 'glCheckFramebufferStatus': func = _glCheckFramebufferStatus; break;
case 'glRenderbufferStorage': func = _glRenderbufferStorage; break;
default: {
- console.log('WARNING: getProcAddress failed for ' + name);
+ Module.printErr('WARNING: getProcAddress failed for ' + name);
func = function() {
- console.log('WARNING: empty replacement for ' + name + ' called, no-op');
+ Module.printErr('WARNING: empty replacement for ' + name + ' called, no-op');
return 0;
};
}
@@ -1236,9 +1256,9 @@ var LibraryGL = {
$GLImmediate__postset: 'Browser.moduleContextCreatedCallbacks.push(function() { GL.immediate.init() });',
$GLImmediate__deps: ['$Browser'],
$GLImmediate: {
- // Vertex and index data
- maxElements: 10240,
MAX_TEXTURES: 7,
+
+ // Vertex and index data
vertexData: null, // current vertex data. either tempData (glBegin etc.) or a view into the heap (gl*Pointer). Default view is F32
vertexDataU8: null, // U8 view
tempData: null,
@@ -1297,6 +1317,46 @@ var LibraryGL = {
attrib.pointer = pointer;
},
+ // Temporary buffers
+ MAX_TEMP_BUFFER_SIZE: 2*1024*1024,
+ tempBufferIndexLookup: null,
+ tempVertexBuffers: null,
+ tempIndexBuffers: null,
+
+ generateTempBuffers: function() {
+ function ceilPower2(x) {
+ return Math.pow(2, Math.ceil(Math.log(i || 1)/Math.log(2)));
+ }
+ this.tempBufferIndexLookup = new Uint8Array(this.MAX_TEMP_BUFFER_SIZE+1);
+ var last = -1, curr = -1;
+ for (var i = 0; i <= this.MAX_TEMP_BUFFER_SIZE; i++) {
+ var size = ceilPower2(i);
+ if (size != last) {
+ curr++;
+ last = size;
+ }
+ this.tempBufferIndexLookup[i] = curr;
+ }
+ this.tempVertexBuffers = [];
+ this.tempIndexBuffers = [];
+ last = -1;
+ for (var i = 0; i <= this.MAX_TEMP_BUFFER_SIZE; i++) {
+ var size = ceilPower2(i);
+ curr = this.tempBufferIndexLookup[i];
+ if (size != last) {
+ this.tempVertexBuffers[curr] = Module.ctx.createBuffer();
+ Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.tempVertexBuffers[curr]);
+ Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW);
+ Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null);
+ this.tempIndexBuffers[curr] = Module.ctx.createBuffer();
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.tempIndexBuffers[curr]);
+ Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, size, Module.ctx.DYNAMIC_DRAW);
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null);
+ last = size;
+ }
+ }
+ },
+
// Renderers
addRendererComponent: function(name, size, type) {
if (!this.rendererComponents[name]) {
@@ -1338,7 +1398,7 @@ var LibraryGL = {
}
if (!cacheItem.renderer) {
#if GL_DEBUG
- console.log('generating renderer for ' + JSON.stringify(attributes));
+ Module.printErr('generating renderer for ' + JSON.stringify(attributes));
#endif
cacheItem.renderer = this.createRenderer();
}
@@ -1545,20 +1605,12 @@ var LibraryGL = {
}
// Buffers for data
- this.tempData = new Float32Array(this.maxElements);
- this.indexData = new Uint16Array(this.maxElements);
+ this.tempData = new Float32Array(this.MAX_TEMP_BUFFER_SIZE >> 2);
+ this.indexData = new Uint16Array(this.MAX_TEMP_BUFFER_SIZE >> 1);
this.vertexDataU8 = new Uint8Array(this.tempData.buffer);
- this.vertexObject = Module.ctx.createBuffer();
- Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.vertexObject);
- Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, this.maxElements*4, Module.ctx.DYNAMIC_DRAW);
- Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null);
-
- this.indexObject = Module.ctx.createBuffer();
- Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.indexObject);
- Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, this.maxElements*2, Module.ctx.DYNAMIC_DRAW);
- Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, null);
+ this.generateTempBuffers();
this.clientColor = new Float32Array([1, 1, 1, 1]);
@@ -1572,17 +1624,30 @@ var LibraryGL = {
}
GL.immediate.prepareClientAttributes(count, false);
GL.immediate.mode = mode;
+ if (!GL.currArrayBuffer) {
+ GL.immediate.vertexData = {{{ makeHEAPView('F32', 'GL.immediate.vertexPointer', 'GL.immediate.vertexPointer + (first+count)*GL.immediate.stride') }}}; // XXX assuming float
+ GL.immediate.firstVertex = first;
+ GL.immediate.lastVertex = first + count;
+ }
GL.immediate.flush(null, first);
};
- _glDrawElements = function(mode, count, type, indices) {
- if (GL.immediate.totalEnabledClientAttributes == 0 && mode <= 6) {
+ _glDrawElements = function(mode, count, type, indices, start, end) { // start, end are given if we come from glDrawRangeElements
+ if (GL.immediate.totalEnabledClientAttributes == 0 && mode <= 6 && GL.currElementArrayBuffer) {
Module.ctx.drawElements(mode, count, type, indices);
return;
}
+ if (!GL.currElementArrayBuffer) {
+ assert(type == Module.ctx.UNSIGNED_SHORT); // We can only emulate buffers of this kind, for now
+ }
GL.immediate.prepareClientAttributes(count, false);
GL.immediate.mode = mode;
- GL.immediate.flush(count, indices);
+ if (!GL.currArrayBuffer) {
+ GL.immediate.firstVertex = end ? start : TOTAL_MEMORY; // if we don't know the start, set an invalid value and we will calculate it later from the indices
+ GL.immediate.lastVertex = end ? end+1 : 0;
+ GL.immediate.vertexData = {{{ makeHEAPView('F32', 'GL.immediate.vertexPointer', '(end ? GL.immediate.vertexPointer + (end+1)*GL.immediate.stride : TOTAL_MEMORY)') }}}; // XXX assuming float
+ }
+ GL.immediate.flush(count, 0, indices);
};
},
@@ -1629,14 +1694,15 @@ var LibraryGL = {
if (!beginEnd) {
bytes *= count;
if (!GL.currArrayBuffer) {
- GL.immediate.vertexData = {{{ makeHEAPView('F32', 'start', 'start + bytes') }}}; // XXX assuming float
+ GL.immediate.vertexPointer = start;
}
GL.immediate.vertexCounter = bytes / 4; // XXX assuming float
}
},
- flush: function(numProvidedIndexes, startIndex) {
+ flush: function(numProvidedIndexes, startIndex, ptr) {
startIndex = startIndex || 0;
+ ptr = ptr || 0;
var renderer = this.getRenderer();
@@ -1644,10 +1710,31 @@ var LibraryGL = {
var numVertexes = 4 * this.vertexCounter / GL.immediate.stride; // XXX assuming float
assert(numVertexes % 1 == 0);
- var restoreElementArrayBuffer = false;
+ var emulatedElementArrayBuffer = false;
var numIndexes = 0;
if (numProvidedIndexes) {
numIndexes = numProvidedIndexes;
+ if (!GL.currArrayBuffer && GL.immediate.firstVertex > GL.immediate.lastVertex) {
+ // Figure out the first and last vertex from the index data
+ assert(!GL.currElementArrayBuffer); // If we are going to upload array buffer data, we need to find which range to
+ // upload based on the indices. If they are in a buffer on the GPU, that is very
+ // inconvenient! So if you do not have an array buffer, you should also not have
+ // an element array buffer. But best is to use both buffers!
+ for (var i = 0; i < numProvidedIndexes; i++) {
+ var currIndex = {{{ makeGetValue('ptr', 'i*2', 'i16', null, 1) }}};
+ GL.immediate.firstVertex = Math.min(GL.immediate.firstVertex, currIndex);
+ GL.immediate.lastVertex = Math.max(GL.immediate.lastVertex, currIndex+1);
+ }
+ }
+ if (!GL.currElementArrayBuffer) {
+ // If no element array buffer is bound, then indices is a literal pointer to clientside data
+ assert(numProvidedIndexes << 1 <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (a)');
+ var indexBuffer = GL.immediate.tempIndexBuffers[GL.immediate.tempBufferIndexLookup[numProvidedIndexes << 1]];
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ Module.ctx.bufferSubData(Module.ctx.ELEMENT_ARRAY_BUFFER, 0, {{{ makeHEAPView('U16', 'ptr', 'ptr + (numProvidedIndexes << 1)') }}});
+ ptr = 0;
+ emulatedElementArrayBuffer = true;
+ }
} else if (GL.immediate.mode > 6) { // above GL_TRIANGLE_FAN are the non-GL ES modes
if (GL.immediate.mode == 7) { // GL_QUADS
var numQuads = numVertexes / 4;
@@ -1664,16 +1751,21 @@ var LibraryGL = {
} else {
throw 'unsupported immediate mode ' + GL.immediate.mode;
}
- assert(numIndexes < GL.immediate.maxElements, 'too many immediate mode indexes');
-
- Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.indexObject);
+ assert(numIndexes << 1 <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (b)');
+ var indexBuffer = GL.immediate.tempIndexBuffers[GL.immediate.tempBufferIndexLookup[numIndexes << 1]];
+ Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
Module.ctx.bufferSubData(Module.ctx.ELEMENT_ARRAY_BUFFER, 0, this.indexData.subarray(0, numIndexes));
- restoreElementArrayBuffer = true;
+ emulatedElementArrayBuffer = true;
}
if (!GL.currArrayBuffer) {
Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.vertexObject);
- Module.ctx.bufferSubData(Module.ctx.ARRAY_BUFFER, 0, this.vertexData.subarray(0, this.vertexCounter));
+ var start = GL.immediate.firstVertex*GL.immediate.stride;
+ var end = GL.immediate.lastVertex*GL.immediate.stride;
+ assert(end <= GL.immediate.MAX_TEMP_BUFFER_SIZE, 'too much vertex data');
+ var vertexBuffer = GL.immediate.tempVertexBuffers[GL.immediate.tempBufferIndexLookup[end]];
+ Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, vertexBuffer);
+ Module.ctx.bufferSubData(Module.ctx.ARRAY_BUFFER, start, this.vertexData.subarray(start >> 2, end >> 2));
}
// Render
@@ -1684,10 +1776,7 @@ var LibraryGL = {
renderer.prepare();
if (numIndexes) {
- if (!numProvidedIndexes) {
- Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.indexObject);
- }
- Module.ctx.drawElements(Module.ctx.TRIANGLES, numIndexes, Module.ctx.UNSIGNED_SHORT, startIndex);
+ Module.ctx.drawElements(Module.ctx.TRIANGLES, numIndexes, Module.ctx.UNSIGNED_SHORT, ptr);
} else {
Module.ctx.drawArrays(GL.immediate.mode, startIndex, numVertexes);
}
@@ -1697,7 +1786,7 @@ var LibraryGL = {
if (!GL.currArrayBuffer) {
Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null);
}
- if (restoreElementArrayBuffer) {
+ if (emulatedElementArrayBuffer) {
Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, GL.buffers[GL.currElementArrayBuffer] || null);
}
if (!GL.currProgram) {
@@ -1722,6 +1811,8 @@ var LibraryGL = {
glEnd: function() {
GL.immediate.prepareClientAttributes(GL.immediate.rendererComponents['V'], true);
+ GL.immediate.firstVertex = 0;
+ GL.immediate.lastVertex = GL.immediate.vertexCounter / (GL.immediate.stride >> 2);
GL.immediate.flush();
GL.immediate.disableBeginEndClientAttributes();
},
@@ -1734,7 +1825,7 @@ var LibraryGL = {
GL.immediate.vertexData[GL.immediate.vertexCounter++] = y;
GL.immediate.vertexData[GL.immediate.vertexCounter++] = z || 0;
#if ASSERTIONS
- assert(GL.immediate.vertexCounter < GL.immediate.maxElements);
+ assert(GL.immediate.vertexCounter << 2 < GL.immediate.MAX_TEMP_BUFFER_SIZE);
#endif
GL.immediate.addRendererComponent('V', 3, Module.ctx.FLOAT);
},
@@ -1840,6 +1931,11 @@ var LibraryGL = {
glNormal3f: function(){}, // TODO
+ // Additional non-GLES rendering calls
+
+ glDrawRangeElements: function(mode, start, end, count, type, indices) {
+ _glDrawElements(mode, count, type, indices, start, end);
+ },
// ClientState/gl*Pointer
@@ -1922,7 +2018,7 @@ var LibraryGL = {
glLoadMatrixf: function(matrix) {
#if GL_DEBUG
- console.log('glLoadMatrixf receiving: ' + Array.prototype.slice.call(HEAPF32.subarray(matrix >> 2, (matrix >> 2) + 16)));
+ if (GL.debug) Module.printErr('glLoadMatrixf receiving: ' + Array.prototype.slice.call(HEAPF32.subarray(matrix >> 2, (matrix >> 2) + 16)));
#endif
GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}, GL.immediate.matrix[GL.immediate.currentMatrix]);
},
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 85a04d27..33a33c09 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -28,6 +28,7 @@ var LibrarySDL = {
mouseX: 0,
mouseY: 0,
buttonState: 0,
+ DOMButtons: [0, 0, 0],
DOMEventToSDLEvent: {},
@@ -42,7 +43,7 @@ var LibrarySDL = {
17: 305, // control (right, or left)
18: 308, // alt
- 109: 45, // minus
+ 173: 45, // minus
16: 304, // shift
96: 88 | 1<<10, // keypad 0
@@ -293,7 +294,14 @@ var LibrarySDL = {
pageX: event.pageX,
pageY: event.pageY
};
+ } else if (event.type == 'mousedown') {
+ SDL.DOMButtons[event.button] = 1;
+ } else if (event.type == 'mouseup') {
+ if (!SDL.DOMButtons[event.button]) return false; // ignore extra ups, can happen if we leave the canvas while pressing down, then return,
+ // since we add a mouseup in that case
+ SDL.DOMButtons[event.button] = 0;
}
+
SDL.events.push(event);
if (SDL.events.length >= 10000) {
Module.printErr('SDL event queue full, dropping earliest event');
@@ -305,6 +313,20 @@ var LibrarySDL = {
event.preventDefault();
}
break;
+ case 'mouseout':
+ // Un-press all pressed mouse buttons, because we might miss the release outside of the canvas
+ for (var i = 0; i < 3; i++) {
+ if (SDL.DOMButtons[i]) {
+ SDL.events.push({
+ type: 'mouseup',
+ button: i,
+ pageX: event.pageX,
+ pageY: event.pageY
+ });
+ SDL.DOMButtons[i] = 0;
+ }
+ }
+ break;
}
return false;
},
@@ -382,8 +404,7 @@ var LibrarySDL = {
SDL.mouseY = y;
break;
}
- default:
- throw 'Unhandled SDL event: ' + event.type;
+ default: throw 'Unhandled SDL event: ' + event.type;
}
},
@@ -475,8 +496,39 @@ var LibrarySDL = {
return -1; // -1 == all modes are ok. TODO
},
+ SDL_VideoModeOK: function(width, height, depth, flags) {
+ // SDL_VideoModeOK returns 0 if the requested mode is not supported under any bit depth, or returns the
+ // bits-per-pixel of the closest available mode with the given width, height and requested surface flags
+ return depth; // all modes are ok.
+ },
+
+ SDL_VideoDriverName: function(buf, max_size) {
+ if (SDL.startTime === null) {
+ return 0; //return NULL
+ }
+ //driverName - emscripten_sdl_driver
+ var driverName = [101, 109, 115, 99, 114, 105, 112, 116, 101,
+ 110, 95, 115, 100, 108, 95, 100, 114, 105, 118, 101, 114];
+
+ var index = 0;
+ var size = driverName.length;
+
+ if (max_size <= size) {
+ size = max_size - 1; //-1 cause null-terminator
+ }
+
+ while (index < size) {
+ var value = driverName[index];
+ {{{ makeSetValue('buf', 'index', 'value', 'i8') }}};
+ index++;
+ }
+
+ {{{ makeSetValue('buf', 'index', '0', 'i8') }}};
+ return buf;
+ },
+
SDL_SetVideoMode: function(width, height, depth, flags) {
- ['mousedown', 'mouseup', 'mousemove', 'DOMMouseScroll'].forEach(function(event) {
+ ['mousedown', 'mouseup', 'mousemove', 'DOMMouseScroll', 'mouseout'].forEach(function(event) {
Module['canvas'].addEventListener(event, SDL.receiveEvent, true);
});
Module['canvas'].width = width;
@@ -484,6 +536,10 @@ var LibrarySDL = {
return SDL.screen = SDL.makeSurface(width, height, flags, true, 'screen');
},
+ SDL_QuitSubSystem: function(flags) {
+ Module.print('SDL_QuitSubSystem called (and ignored)');
+ },
+
SDL_Quit: function() {
for (var i = 0; i < SDL.audios; i++) {
SDL.audios[i].pause();
@@ -597,6 +653,10 @@ var LibrarySDL = {
// We actually do the whole screen in Unlock...
},
+ SDL_UpdateRects: function(surf, numrects, rects) {
+ // We actually do the whole screen in Unlock...
+ },
+
SDL_Delay: function(delay) {
throw 'SDL_Delay called! Potential infinite loop, quitting. ' + new Error().stack;
},
@@ -614,6 +674,11 @@ var LibrarySDL = {
return SDL.keyboardState;
},
+ SDL_GetKeyState__deps: ['SDL_GetKeyboardState'],
+ SDL_GetKeyState: function() {
+ return _SDL_GetKeyboardState();
+ },
+
SDL_GetModState: function() {
// TODO: numlock, capslock, etc.
return (SDL.shiftKey ? 0x0001 & 0x0002 : 0) | // KMOD_LSHIFT & KMOD_RSHIFT
diff --git a/src/parseTools.js b/src/parseTools.js
index 158e6340..e13d8807 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1155,7 +1155,7 @@ function makeHEAPView(which, start, end) {
// Assumes USE_TYPED_ARRAYS == 2
var size = parseInt(which.replace('U', '').replace('F', ''))/8;
var mod = size == 1 ? '' : ('>>' + log2(size));
- return 'HEAP' + which + '.subarray(' + start + mod + ',' + end + mod + ')';
+ return 'HEAP' + which + '.subarray((' + start + ')' + mod + ',(' + end + ')' + mod + ')';
}
var PLUS_MUL = set('+', '*');
diff --git a/src/shell.html b/src/shell.html
index 404c9c11..dad50b9f 100644
--- a/src/shell.html
+++ b/src/shell.html
@@ -36,6 +36,13 @@
element.scrollTop = 99999; // focus on bottom
};
})(),
+ printErr: function(text) {
+ if (0) { // XXX disabled for safety typeof dump == 'function') {
+ dump(text + '\n'); // fast, straight to the real console
+ } else {
+ console.log(text);
+ }
+ },
canvas: document.getElementById('canvas'),
setStatus: function(text) {
if (Module.setStatus.interval) clearInterval(Module.setStatus.interval);