aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--tests/cubegeom_normal_dap.c291
-rw-r--r--tests/cubegeom_normal_dap_far.c289
-rw-r--r--tests/cubegeom_normal_dap_far_glda.c280
-rw-r--r--tests/cubegeom_normal_dap_far_range.c289
-rw-r--r--tests/glshaderinfo.cpp52
-rwxr-xr-xtests/runner.py48
12 files changed, 1495 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);
diff --git a/tests/cubegeom_normal_dap.c b/tests/cubegeom_normal_dap.c
new file mode 100644
index 00000000..f811c586
--- /dev/null
+++ b/tests/cubegeom_normal_dap.c
@@ -0,0 +1,291 @@
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void verify() {
+ int width = 640, height = 480;
+ unsigned char *data = (unsigned char*)malloc(width*height*4);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ int sum = 0;
+ for (int x = 0; x < width*height*4; x++) {
+ if (x % 4 != 3) sum += x * data[x];
+ }
+#if EMSCRIPTEN
+ int result = sum;
+ REPORT_RESULT();
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL );
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ glClearColor( 0, 0, 0, 0 );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Create a texture
+
+ GLuint texture;
+ glGenTextures( 1, &texture );
+ glBindTexture( GL_TEXTURE_2D, texture );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte textureData[16*16*4];
+ for (int x = 0; x < 16; x++) {
+ for (int y = 0; y < 16; y++) {
+ *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8);
+ }
+ }
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, textureData );
+
+ // Create a second texture
+
+ GLuint texture2;
+ glGenTextures( 1, &texture2 );
+ glBindTexture( GL_TEXTURE_2D, texture2 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ GLubyte texture2Data[] = { 0xff, 0, 0, 0xff,
+ 0, 0xff, 0, 0xaa,
+ 0, 0, 0xff, 0x55,
+ 0x80, 0x90, 0x70, 0 };
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texture2Data );
+
+ // BEGIN
+
+#if USE_GLEW
+ glewInit();
+#endif
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048);
+ glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048);
+ glRotatef(-30, 1, 1, 1);
+ //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 };
+ //glLoadMatrixf(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ GLfloat matrixData[] = { -1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1 };
+ glLoadMatrixf(matrixData);
+ //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown
+
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ GLuint arrayBuffer, elementBuffer;
+ glGenBuffers(1, &arrayBuffer);
+ glGenBuffers(1, &elementBuffer);
+
+ GLubyte arrayData[] = {
+/*
+[0, 0, 0, 67] ==> 128 float
+[0, 0, 128, 67] ==> 256 float
+[0, 0, 0, 68] ==> 512 float
+[0, 0, 128, 68] ==> 1024 float
+
+[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 11, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 23, 20, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 35, 30, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2
+ 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 47, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 51, 50, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4
+ 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 64, 60, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5
+ 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 70, 70, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6
+ 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 89, 80, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 12