diff options
-rw-r--r-- | src/library.js | 25 | ||||
-rw-r--r-- | src/library_browser.js | 8 | ||||
-rw-r--r-- | src/library_gl.js | 198 | ||||
-rw-r--r-- | src/library_sdl.js | 73 | ||||
-rw-r--r-- | src/parseTools.js | 2 | ||||
-rw-r--r-- | src/shell.html | 7 | ||||
-rw-r--r-- | tests/cubegeom_normal_dap.c | 291 | ||||
-rw-r--r-- | tests/cubegeom_normal_dap_far.c | 289 | ||||
-rw-r--r-- | tests/cubegeom_normal_dap_far_glda.c | 280 | ||||
-rw-r--r-- | tests/cubegeom_normal_dap_far_range.c | 289 | ||||
-rw-r--r-- | tests/glshaderinfo.cpp | 52 | ||||
-rwxr-xr-x | tests/runner.py | 48 |
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 |