diff options
-rw-r--r-- | src/library.js | 28 | ||||
-rw-r--r-- | src/library_gl.js | 481 | ||||
-rw-r--r-- | src/library_sdl.js | 15 | ||||
-rw-r--r-- | src/preamble.js | 37 | ||||
-rw-r--r-- | system/include/GL/glut.h | 596 | ||||
-rw-r--r-- | system/include/GLES2/gl2.h | 621 | ||||
-rw-r--r-- | system/include/GLES2/gl2platform.h | 30 | ||||
-rw-r--r-- | system/include/KHR/khrplatform.h | 277 | ||||
-rwxr-xr-x | tests/runner.py | 125 |
9 files changed, 2143 insertions, 67 deletions
diff --git a/src/library.js b/src/library.js index 5a429131..89e52243 100644 --- a/src/library.js +++ b/src/library.js @@ -4682,6 +4682,34 @@ LibraryManager.library = { }, nanf: 'nan', + sincos: function(x, sine, cosine) { + var sineVal = Math.sin(x), + cosineVal = Math.cos(x); + {{{ makeSetValue('sine', '0', 'sineVal', 'double') }}}; + {{{ makeSetValue('cosine', '0', 'cosineVal', 'double') }}}; + }, + + sincosf: function(x, sine, cosine) { + var sineVal = Math.sin(x), + cosineVal = Math.cos(x); + {{{ makeSetValue('sine', '0', 'sineVal', 'float') }}}; + {{{ makeSetValue('cosine', '0', 'cosineVal', 'float') }}}; + }, + + __div_t_struct_layout: Runtime.generateStructInfo([ + ['i32', 'quot'], + ['i32', 'rem'], + ]), + div__deps: ['__div_t_struct_layout'], + div: function(divt, numer, denom) { + var quot = Math.floor(numer / denom); + var rem = numer - quot * denom; + var offset = ___div_t_struct_layout.rem; + {{{ makeSetValue('divt', '0', 'quot', 'i32') }}}; + {{{ makeSetValue('divt', 'offset', 'rem', 'i32') }}}; + return divt; + }, + __fpclassifyf: function(x) { if (isNaN(x)) return {{{ cDefine('FP_NAN') }}}; if (!isFinite(x)) return {{{ cDefine('FP_INFINITE') }}}; diff --git a/src/library_gl.js b/src/library_gl.js index 2be881df..e1a7c73b 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -4,8 +4,35 @@ var LibraryGL = { $GL: { - textures: {}, - textureCounter: 0, + hashtable: function(name) { + if (!this._hashtables) { + this._hashtables = {}; + } + if (!(name in this._hashtables)) { + this._hashtables[name] = { + table: {}, + counter: 0, + add: function(obj) { + var id = this.counter++; + this.table[id] = obj; + return id; + }, + get: function(id) { +#if ASSERTIONS + assert(id < this.counter, "Invalid id " + id + " for the hashtable " + name); +#endif + return this.table[id]; + }, + remove: function(id) { +#if ASSERTIONS + assert(id < this.counter, "Invalid id " + id + " for the hashtable " + name); +#endif + delete this.table[id]; + } + }; + } + return this._hashtables[name]; + }, }, glGetString: function(name_) { @@ -24,7 +51,7 @@ var LibraryGL = { glGetIntegerv: function(name_, p) { switch(name_) { case Module.ctx.MAX_TEXTURE_SIZE: - IHEAP[p] = Module.ctx.getParameter(name_); + {{{ makeSetValue('p', '0', 'Module.ctx.getParameter(name_)', 'i32') }}}; break; default: throw 'Failure: Invalid glGetIntegerv value: ' + name_; @@ -34,78 +61,476 @@ var LibraryGL = { glGenTextures__deps: ['$GL'], glGenTextures: function(n, textures) { for (var i = 0; i < n; i++) { - var id = GL.textureCounter++; - GL.textures[id] = Module.ctx.createTexture(); - IHEAP[textures+QUANTUM_SIZE*i] = id; + var id = GL.hashtable("texture").add(Module.ctx.createTexture()); + {{{ makeSetValue('textures', 'i', 'id', 'i32') }}}; } }, glDeleteTextures: function(n, textures) { for (var i = 0; i < n; i++) { - var id = IHEAP[textures+QUANTUM_SIZE*i]; - Module.ctx.deleteTexture(GL.textures[id]); - delete GL.textures[id]; + var id = {{{ makeGetValue('textures', 'i', 'i32') }}}; + Module.ctx.deleteTexture(GL.hashtable("texture").get(id)); + GL.hashtable("texture").remove(id); } }, glTexImage2D: function(target, level, internalformat, width, height, border, format, type, pixels) { if (pixels) { - pixels = new Uint8Array(IHEAP.slice(pixels, pixels + width*height*4)); // TODO: optimize + pixels = new Uint8Array(Array_copy(pixels, pixels + width*height*4)); // TODO: optimize } Module.ctx.texImage2D(target, level, internalformat, width, height, border, format, type, pixels); }, glTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, type, pixels) { if (pixels) { - pixels = new Uint8Array(IHEAP.slice(pixels, pixels + width*height*4)); // TODO: optimize + pixels = new Uint8Array(Array_copy(pixels, pixels + width*height*4)); // TODO: optimize } Module.ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); }, glBindTexture: function(target, texture) { - Module.ctx.bindTexture(target, GL.textures[texture]); + Module.ctx.bindTexture(target, GL.hashtable("texture").get(texture)); }, - glClearColor: function(red, green, blue, alpha) { - Module.ctx.clearColor(red, green, blue, alpha); + glGenBuffers__deps: ['$GL'], + glGenBuffers: function(n, buffers) { + for (var i = 0; i < n; i++) { + var id = GL.hashtable("buffer").add(Module.ctx.createBuffer()); + {{{ makeSetValue('buffers', 'i', 'id', 'i32') }}}; + } + }, + + glDeleteBuffers: function(n, buffers) { + for (var i = 0; i < n; i++) { + var id = {{{ makeGetValue('buffers', 'i', 'i32') }}}; + Module.ctx.deleteBuffer(GL.hashtable("buffer").get(id)); + GL.hashtable("buffer").remove(id); + } + }, + + glBufferData: function(target, size, data, usage) { + var floatArray = new Float32Array(TypedArray_copy(data, size)); + Module.ctx.bufferData(target, floatArray, usage); + }, + + glBindAttribLocation_deps: ['$GL'], + glGetUniformLocation: function(program, name) { + name = Pointer_stringify(name); + return GL.hashtable("uniform").add( + Module.ctx.getUniformLocation(GL.hashtable("program").get(program), name)); + }, + + glUniform1f: function(Location, v0) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform1f(Location, v0); + }, + + glUniform2f: function(Location, v0, v1) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform2f(Location, v0, v1); + }, + + glUniform3f: function(Location, v0, v1, v2) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform3f(Location, v0, v1, v2); }, - glClear: function(mask) { - Module.ctx.clear(mask); + glUniform4f: function(Location, v0, v1, v2, v3) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform4f(Location, v0, v1, v2, v3); }, - glEnable: function(cap) { - Module.ctx.enable(cap); + glUniform1i: function(Location, v0) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform1i(Location, v0); }, - glScissor: function(x, y, width, height) { - Module.ctx.scissor(x, y, width, height); + glUniform2i: function(Location, v0, v1) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform2i(Location, v0, v1); + }, + + glUniform3i: function(Location, v0, v1, v2) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform3i(Location, v0, v1, v2); + }, + + glUniform4i: function(Location, v0, v1, v2, v3) { + Location = GL.hashtable("uniform").get(Location); + Module.ctx.uniform4i(Location, v0, v1, v2, v3); + }, + + glUniform1fv: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform1fv(Location, value); + }, + + glUniform2fv: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 2; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform2fv(Location, value); + }, + + glUniform3fv: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 3; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform3fv(Location, value); + }, + + glUniform4fv: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 4; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform4fv(Location, value); + }, + + glUniform1fi: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform1fi(Location, value); + }, + + glUniform2fi: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 2; + value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform2fi(Location, value); + }, + + glUniform3fi: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 3; + value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform3fi(Location, value); + }, + + glUniform4fi: function(Location, count, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 4; + value = new Uint32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform4fi(Location, value); + }, + + glUniformMatrix2fv: function(Location, count, transpose, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 4; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniformMatrix2fv(Location, transpose, value); + }, + + glUniformMatrix3fv: function(Location, count, transpose, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 9; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniformMatrix3fv(Location, transpose, value); + }, + + glUniformMatrix4fv: function(Location, count, transpose, value) { + Location = GL.hashtable("uniform").get(Location); + count *= 16; + value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniformMatrix4fv(Location, transpose, value); + }, + + glBindBuffer: function(target, buffer) { + Module.ctx.bindBuffer(target, GL.hashtable("buffer").get(buffer)); + }, + + glVertexAttrib1f: function(index, v0) { + Module.ctx.vertexAttrib1f(index, v0); + }, + + glVertexAttrib2f: function(index, v0, v1) { + Module.ctx.vertexAttrib2f(index, v0, v1); + }, + + glVertexAttrib3f: function(index, v0, v1, v2) { + Module.ctx.vertexAttrib3f(index, v0, v1, v2); + }, + + glVertexAttrib4f: function(index, v0, v1, v2, v3) { + Module.ctx.vertexAttrib4f(index, v0, v1, v2, v3); + }, + + glVertexAttrib1fv: function(index, v) { + v = new Float32Array(TypedArray_copy(v, 1*4)); // TODO: optimize + Module.ctx.vertexAttrib1fv(index, v); + }, + + glVertexAttrib2fv: function(index, v) { + v = new Float32Array(TypedArray_copy(v, 2*4)); // TODO: optimize + Module.ctx.vertexAttrib2fv(index, v); + }, + + glVertexAttrib3fv: function(index, v) { + v = new Float32Array(TypedArray_copy(v, 3*4)); // TODO: optimize + Module.ctx.vertexAttrib3fv(index, v); + }, + + glVertexAttrib4fv: function(index, v) { + v = new Float32Array(TypedArray_copy(v, 4*4)); // TODO: optimize + Module.ctx.vertexAttrib4fv(index, v); + }, + + glVertexAttribPointer: function(index, size, type, normalized, stride, pointer) { + Module.ctx.vertexAttribPointer(index, size, type, normalized, stride, pointer); + }, + + glEnableVertexAttribArray: function(index) { + Module.ctx.enableVertexAttribArray(index); + }, + + glDisableVertexAttribArray: function(index) { + Module.ctx.disableVertexAttribArray(index); + }, + + glDrawArrays: function(mode, first, count) { + Module.ctx.drawArrays(mode, first, count); + }, + + glGetAttribLocation: function(program, name) { + program = GL.hashtable("program").get(program); + name = Pointer_stringify(name); + Module.ctx.getAttribLocation(program, name); + }, + + glCreateShader_deps: ['$GL'], + glCreateShader: function(shaderType) { + var shader = Module.ctx.createShader(shaderType); + return GL.hashtable("shader").add(shader); + }, + + glShaderSource_deps: ['$GL'], + glShaderSource: function(shader, count, string, length) { + var source = ""; + for (var i = 0; i < count; ++i) { + var frag = string[i]; + if (length) { + var len = {{{ makeGetValue('length', 'i', 'i32') }}}; + if (len < 0) { + frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}}); + } else { + frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}}, len); + } + } else { + frag = Pointer_stringify({{{ makeGetValue('string', 'i', 'i32') }}}); + } + if (source.length) { + source += "\n"; + } + source += frag; + } + Module.ctx.shaderSource(GL.hashtable("shader").get(shader), source); + }, + + glCompileShader_deps: ['$GL'], + glCompileShader: function(shader) { + Module.ctx.compileShader(GL.hashtable("shader").get(shader)); + }, + + glGetShaderInfoLog_deps: ['$GL'], + glGetShaderInfoLog: function(shader, maxLength, length, infoLog) { + var log = Module.ctx.getShaderInfoLog(GL.hashtable("shader").get(shader)); + log.slice(0, maxLength - 1); + writeStringToMemory(log, infoLog); + if (length) { + {{{ makeSetValue('length', 'i', 'log.length', 'i32') }}} + } + }, + + glCreateProgram_deps: ['$GL'], + glCreateProgram: function() { + return GL.hashtable("program").add(Module.ctx.createProgram()); + }, + + glAttachShader_deps: ['$GL'], + glAttachShader: function(program, shader) { + Module.ctx.attachShader(GL.hashtable("program").get(program), + GL.hashtable("shader").get(shader)); + }, + + glLinkProgram_deps: ['$GL'], + glLinkProgram: function(program) { + Module.ctx.linkProgram(GL.hashtable("program").get(program)); + }, + + glGetProgramInfoLog_deps: ['$GL'], + glGetProgramInfoLog: function(program, maxLength, length, infoLog) { + var log = Module.ctx.getProgramInfoLog(GL.hashtable("program").get(program)); + // Work around a bug in Chromium which causes getProgramInfoLog to return null + if (!log) { + log = ""; + } + log = log.substr(0, maxLength - 1); + writeStringToMemory(log, infoLog); + if (length) { + {{{ makeSetValue('length', 'i', 'log.length', 'i32') }}} + } + }, + + glUseProgram_deps: ['$Gl'], + glUseProgram: function(program) { + Module.ctx.useProgram(GL.hashtable("program").get(program)); + }, + + glBindAttribLocation_deps: ['$GL'], + glBindAttribLocation: function(program, index, name) { + name = Pointer_stringify(name); + Module.ctx.bindAttribLocation(GL.hashtable("program").get(program), index, name); }, }; -// Ignored stubs for fixed-function pipeline. We will need to emulate this -'begin end matrixMode loadIdentity ortho color3f texCoord2f vertex2f blendFunc pushMatrix popMatrix translatef scalef color4ub enableClientState disableClientState vertexPointer colorPointer normalPointer texCoordPointer drawArrays clientActiveTexture_'.split(' ').forEach(function(name_) { - var cName = 'gl' + name_[0].toUpperCase() + name_.substr(1); - LibraryGL[cName] = function(){}; -}); // Simple pass-through functions -[[0, 'shadeModel fogi fogfv'], - [1, 'clearDepth depthFunc enable disable frontFace cullFace'], +[[0, 'shadeModel fogi fogfv getError'], + [1, 'clearDepth depthFunc enable disable frontFace cullFace clear'], [2, 'pixelStorei'], [3, 'texParameteri texParameterf'], - [4, 'viewport clearColor']].forEach(function(data) { + [4, 'viewport clearColor scissor']].forEach(function(data) { var num = data[0]; var names = data[1]; var args = range(num).map(function(i) { return 'x' + i }).join(', '); var stub = '(function(' + args + ') { ' + (num > 0 ? 'Module.ctx.NAME(' + args + ')' : '') + ' })'; names.split(' ').forEach(function(name_) { var cName = 'gl' + name_[0].toUpperCase() + name_.substr(1); +#if ASSERTIONS + assert(!(cName in LibraryGL), "Cannot reimplement the existing function " + cName); +#endif LibraryGL[cName] = eval(stub.replace('NAME', name_)); //print(cName + ': ' + LibraryGL[cName]); }); }); +var LibraryGLUT = { + $GLUT: { + initTime: null, + idleFunc: null, + keyboardFunc: null, + reshapeFunc: null, + lastX: 0, + lastY: 0, + + onMousemove: function(event) { + GLUT.lastX = event['clientX']; + GLUT.lastY = event['clientY']; + }, + + onKeydown: function(event) { + if (GLUT.keyboardFunc) { + var key = null; + switch (event['keyCode']) { + case 0x70 /*DOM_VK_F1*/: key = 1 /* GLUT_KEY_F1 */; break; + case 0x71 /*DOM_VK_F2*/: key = 2 /* GLUT_KEY_F2 */; break; + case 0x72 /*DOM_VK_F3*/: key = 3 /* GLUT_KEY_F3 */; break; + case 0x73 /*DOM_VK_F4*/: key = 4 /* GLUT_KEY_F4 */; break; + case 0x74 /*DOM_VK_F5*/: key = 5 /* GLUT_KEY_F5 */; break; + case 0x75 /*DOM_VK_F6*/: key = 6 /* GLUT_KEY_F6 */; break; + case 0x76 /*DOM_VK_F7*/: key = 7 /* GLUT_KEY_F7 */; break; + case 0x77 /*DOM_VK_F8*/: key = 8 /* GLUT_KEY_F8 */; break; + case 0x78 /*DOM_VK_F9*/: key = 9 /* GLUT_KEY_F9 */; break; + case 0x79 /*DOM_VK_F10*/: key = 10 /* GLUT_KEY_F10 */; break; + case 0x7a /*DOM_VK_F11*/: key = 11 /* GLUT_KEY_F11 */; break; + case 0x7b /*DOM_VK_F12*/: key = 12 /* GLUT_KEY_F12 */; break; + case 0x25 /*DOM_VK_LEFT*/: key = 100 /* GLUT_KEY_LEFT */; break; + case 0x26 /*DOM_VK_UP*/: key = 101 /* GLUT_KEY_UP */; break; + case 0x27 /*DOM_VK_RIGHT*/: key = 102 /* GLUT_KEY_RIGHT */; break; + case 0x28 /*DOM_VK_DOWN*/: key = 103 /* GLUT_KEY_DOWN */; break; + case 0x21 /*DOM_VK_PAGE_UP*/: key = 104 /* GLUT_KEY_PAGE_UP */; break; + case 0x22 /*DOM_VK_PAGE_DOWN*/: key = 105 /* GLUT_KEY_PAGE_DOWN */; break; + case 0x24 /*DOM_VK_HOME*/: key = 106 /* GLUT_KEY_HOME */; break; + case 0x23 /*DOM_VK_END*/: key = 107 /* GLUT_KEY_END */; break; + case 0x2d /*DOM_VK_INSERT*/: key = 108 /* GLUT_KEY_INSERT */; break; + default: return; + }; + if (key !== null) { + FUNCTION_TABLE[GLUT.keyboardFunc](key, GLUT.lastX, GLUT.lastY); + } + } + }, + }, + + glutInit__deps: ['$GLUT'], + glutInit: function(argcp, argv) { + // Ignore arguments + GLUT.initTime = Date.now(); + window.addEventListener("keydown", GLUT.onKeydown, true); + window.addEventListener("mousemove", GLUT.onMousemove, true); + }, + + glutInitWindowSize: function(width, height) { + Module['canvas'].width = width; + Module['canvas'].height = height; + }, + + glutGet: function(type) { + switch (type) { + case 700: /* GLUT_ELAPSED_TIME */ + var now = Date.now(); + return now - GLUT.initTime; + default: + throw "glutGet(" + type + ") not implemented yet"; + } + }, + + glutDisplayFunc: function(func) { + var RAF = window['setTimeout']; + if (window['requestAnimationFrame']) { + RAF = window['requestAnimationFrame']; + } else if (window['mozRequestAnimationFrame']) { + RAF = window['mozRequestAnimationFrame']; + } else if (window['webkitRequestAnimationFrame']) { + RAF = window['webkitRequestAnimationFrame']; + } else if (window['msRequestAnimationFrame']) { + RAF = window['msRequestAnimationFrame']; + } + RAF.apply(window, [function() { + if (GLUT.reshapeFunc) { + FUNCTION_TABLE[GLUT.reshapeFunc](Module['canvas'].width, + Module['canvas'].height); + } + if (GLUT.idleFunc) { + FUNCTION_TABLE[GLUT.idleFunc](); + } + FUNCTION_TABLE[func](); + _glutDisplayFunc(func); + }]); + }, + + glutIdleFunc: function(func) { + GLUT.idleFunc = func; + }, + + glutSpecialFunc: function(func) { + GLUT.keyboardFunc = func; + }, + + glutReshapeFunc: function(func) { + GLUT.reshapeFunc = func; + }, + + glutCreateWindow: function(name) { + try { + var ctx = Module.canvas.getContext('experimental-webgl'); + if (!ctx) throw 'Could not create canvas :('; + Module.ctx = ctx; + // Set the background of the canvas to black, because glut gives us a + // window which has a black background by default. + Module.canvas.style.backgroundColor = "black"; + } catch (e) { + Module.print('(canvas not available)'); + } + }, + + glutInitDisplayMode: function(mode) {}, + glutMainLoop: function() {}, + glutSwapBuffers: function() {}, + glutPostRedisplay: function() {}, +}; + mergeInto(LibraryManager.library, LibraryGL); +mergeInto(LibraryManager.library, LibraryGLUT); diff --git a/src/library_sdl.js b/src/library_sdl.js index ce26a106..d438fc23 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -176,6 +176,11 @@ mergeInto(LibraryManager.library, { try { var ctx = Module.canvas.getContext(useWebGL ? 'experimental-webgl' : '2d'); if (!ctx) throw 'Could not create canvas :('; + if (useWebGL) { + // Set the background of the WebGL canvas to black, because SDL gives us a + // window which has a black background by default. + Module.canvas.style.backgroundColor = "black"; + } return Module.ctx = ctx; } catch (e) { Module.print('(canvas not available)'); @@ -555,5 +560,15 @@ mergeInto(LibraryManager.library, { // SDL Mixer Mix_OpenAudio: function() { return -1 }, + + SDL_AddTimer: function(interval, callback, param) { + return window.setTimeout(function() { + FUNCTION_TABLE[callback](interval, param); + }, interval); + }, + SDL_RemoveTimer: function(id) { + window.clearTimeout(id); + return true; + }, }); diff --git a/src/preamble.js b/src/preamble.js index b9da766f..5470ff39 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -496,16 +496,18 @@ function allocate(slab, types, allocator) { } Module['allocate'] = allocate; -function Pointer_stringify(ptr) { +function Pointer_stringify(ptr, /* optional */ length) { + var nullTerminated = typeof(length) == "undefined"; var ret = ""; var i = 0; var t; var nullByte = String.fromCharCode(0); while (1) { t = String.fromCharCode({{{ makeGetValue('ptr', 'i', 'i8', 0, 1) }}}); - if (t == nullByte) { break; } else {} + if (nullTerminated && t == nullByte) { break; } else {} ret += t; i += 1; + if (!nullTerminated && i == length) { break; } } return ret; } @@ -690,6 +692,18 @@ function Array_copy(ptr, num) { } Module['Array_copy'] = Array_copy; +// Copies a list of num items on the HEAP into a +// JavaScript typed array. +function TypedArray_copy(ptr, num) { + // TODO: optimize this! + var arr = new Uint8Array(num); + for (var i = 0; i < num; ++i) { + arr[i] = {{{ makeGetValue('ptr', 'i', 'i8') }}}; + } + return arr.buffer; +} +Module['TypedArray_copy'] = TypedArray_copy; + function String_len(ptr) { var i = 0; while ({{{ makeGetValue('ptr', 'i', 'i8') }}}) i++; // Note: should be |!= 0|, technically. But this helps catch bugs with undefineds @@ -750,6 +764,25 @@ function intArrayToString(array) { } Module['intArrayToString'] = intArrayToString; +// Write a Javascript array to somewhere in the heap +function writeStringToMemory(string, buffer, dontAddNull) { + var i = 0; + while (i < string.length) { + var chr = string.charCodeAt(i); + if (chr > 0xFF) { +#if ASSERTIONS + assert(false, 'Character code ' + chr + ' (' + string[i] + ') at offset ' + i + ' not in 0x00-0xFF.'); +#endif + chr &= 0xFF; + } + {{{ makeSetValue('buffer', 'i', 'chr', 'i8') }}} + i = i + 1; + } + if (!dontAddNull) { + {{{ makeSetValue('buffer', 'i', '0', 'i8') }}} + } +} + var STRING_TABLE = []; {{{ unSign }}} diff --git a/system/include/GL/glut.h b/system/include/GL/glut.h new file mode 100644 index 00000000..e0692adb --- /dev/null +++ b/system/include/GL/glut.h @@ -0,0 +1,596 @@ +#ifndef __glut_h__ +#define __glut_h__ + +/* Copyright (c) Mark J. Kilgard, 1994, 1995, 1996, 1998. */ + +/* This program is freely distributable without licensing fees and is + provided without guarantee or warrantee expressed or implied. This + program is -not- in the public domain. */ + +#if defined(_WIN32) + +/* GLUT 3.7 now tries to avoid including <windows.h> + to avoid name space pollution, but Win32's <GL/gl.h> + needs APIENTRY and WINGDIAPI defined properly. */ +# if 0 +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# else + /* XXX This is from Win32's <windef.h> */ +# ifndef APIENTRY +# define GLUT_APIENTRY_DEFINED +# if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif +# endif + /* XXX This is from Win32's <winnt.h> */ +# ifndef CALLBACK +# if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) +# define CALLBACK __stdcall +# else +# define CALLBACK +# endif +# endif + /* XXX This is from Win32's <wingdi.h> and <winnt.h> */ +# ifndef WINGDIAPI +# define GLUT_WINGDIAPI_DEFINED +# define WINGDIAPI __declspec(dllimport) +# endif + /* XXX This is from Win32's <ctype.h> */ +# ifndef _WCHAR_T_DEFINED +typedef unsigned short wchar_t; +# define _WCHAR_T_DEFINED +# endif +# endif + +#pragma comment (lib, "winmm.lib") /* link with Windows MultiMedia lib */ +#pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */ +#pragma comment (lib, "glu32.lib") /* link with OpenGL Utility lib */ +#pragma comment (lib, "glut32.lib") /* link with Win32 GLUT lib */ + +#pragma warning (disable:4244) /* Disable bogus conversion warnings. */ +#pragma warning (disable:4305) /* VC++ 5.0 version of above warning. */ + +#endif + +#include <GL/gl.h> +#include <GL/glu.h> + +/* define APIENTRY and CALLBACK to null string if we aren't on Win32 */ +#if !defined(_WIN32) +#define APIENTRY +#define GLUT_APIENTRY_DEFINED +#define CALLBACK +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + GLUT API revision history: + + GLUT_API_VERSION is updated to reflect incompatible GLUT + API changes (interface changes, semantic changes, deletions, + or additions). + + GLUT_API_VERSION=1 First public release of GLUT. 11/29/94 + + GLUT_API_VERSION=2 Added support for OpenGL/GLX multisampling, + extension. Supports new input devices like tablet, dial and button + box, and Spaceball. Easy to query OpenGL extensions. + + GLUT_API_VERSION=3 glutMenuStatus added. + + GLUT_API_VERSION=4 glutInitDisplayString, glutWarpPointer, + glutBitmapLength, glutStrokeLength, glutWindowStatusFunc, dynamic + video resize subAPI, glutPostWindowRedisplay, glutKeyboardUpFunc, + glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, + glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). +**/ +#ifndef GLUT_API_VERSION /* allow this to be overriden */ +#define GLUT_API_VERSION 3 +#endif + +/** + GLUT implementation revision history: + + GLUT_XLIB_IMPLEMENTATION is updated to reflect both GLUT + API revisions and implementation revisions (ie, bug fixes). + + GLUT_XLIB_IMPLEMENTATION=1 mjk's first public release of + GLUT Xlib-based implementation. 11/29/94 + + GLUT_XLIB_IMPLEMENTATION=2 mjk's second public release of + GLUT Xlib-based implementation providing GLUT version 2 + interfaces. + + GLUT_XLIB_IMPLEMENTATION=3 mjk's GLUT 2.2 images. 4/17/95 + + GLUT_XLIB_IMPLEMENTATION=4 mjk's GLUT 2.3 images. 6/?/95 + + GLUT_XLIB_IMPLEMENTATION=5 mjk's GLUT 3.0 images. 10/?/95 + + GLUT_XLIB_IMPLEMENTATION=7 mjk's GLUT 3.1+ with glutWarpPoitner. 7/24/96 + + GLUT_XLIB_IMPLEMENTATION=8 mjk's GLUT 3.1+ with glutWarpPoitner + and video resize. 1/3/97 + + GLUT_XLIB_IMPLEMENTATION=9 mjk's GLUT 3.4 release with early GLUT 4 routines. + + GLUT_XLIB_IMPLEMENTATION=11 Mesa 2.5's GLUT 3.6 release. + + GLUT_XLIB_IMPLEMENTATION=12 mjk's GLUT 3.6 release with early GLUT 4 routines + signal handling. + + GLUT_XLIB_IMPLEMENTATION=13 mjk's GLUT 3.7 release with GameGLUT support. +**/ +#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ +#define GLUT_XLIB_IMPLEMENTATION 13 +#endif + +/* Display mode bit masks. */ +#define GLUT_RGB 0 +#define GLUT_RGBA GLUT_RGB +#define GLUT_INDEX 1 +#define GLUT_SINGLE 0 +#define GLUT_DOUBLE 2 +#define GLUT_ACCUM 4 +#define GLUT_ALPHA 8 +#define GLUT_DEPTH 16 +#define GLUT_STENCIL 32 +#if (GLUT_API_VERSION >= 2) +#define GLUT_MULTISAMPLE 128 +#define GLUT_STEREO 256 +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_LUMINANCE 512 +#endif + +/* Mouse buttons. */ +#define GLUT_LEFT_BUTTON 0 +#define GLUT_MIDDLE_BUTTON 1 +#define GLUT_RIGHT_BUTTON 2 + +/* Mouse button state. */ +#define GLUT_DOWN 0 +#define GLUT_UP 1 + +#if (GLUT_API_VERSION >= 2) +/* function keys */ +#define GLUT_KEY_F1 1 +#define GLUT_KEY_F2 2 +#define GLUT_KEY_F3 3 +#define GLUT_KEY_F4 4 +#define GLUT_KEY_F5 5 +#define GLUT_KEY_F6 6 +#define GLUT_KEY_F7 7 +#define GLUT_KEY_F8 8 +#define GLUT_KEY_F9 9 +#define GLUT_KEY_F10 10 +#define GLUT_KEY_F11 11 +#define GLUT_KEY_F12 12 +/* directional keys */ +#define GLUT_KEY_LEFT 100 +#define GLUT_KEY_UP 101 +#define GLUT_KEY_RIGHT 102 +#define GLUT_KEY_DOWN 103 +#define GLUT_KEY_PAGE_UP 104 +#define GLUT_KEY_PAGE_DOWN 105 +#define GLUT_KEY_HOME 106 +#define GLUT_KEY_END 107 +#define GLUT_KEY_INSERT 108 +#endif + +/* Entry/exit state. */ +#define GLUT_LEFT 0 +#define GLUT_ENTERED 1 + +/* Menu usage state. */ +#define GLUT_MENU_NOT_IN_USE 0 +#define GLUT_MENU_IN_USE 1 + +/* Visibility state. */ +#define GLUT_NOT_VISIBLE 0 +#define GLUT_VISIBLE 1 + +/* Window status state. */ +#define GLUT_HIDDEN 0 +#define GLUT_FULLY_RETAINED 1 +#define GLUT_PARTIALLY_RETAINED 2 +#define GLUT_FULLY_COVERED 3 + +/* Color index component selection values. */ +#define GLUT_RED 0 +#define GLUT_GREEN 1 +#define GLUT_BLUE 2 + +/* Layers for use. */ +#define GLUT_NORMAL 0 +#define GLUT_OVERLAY 1 + +#if defined(_WIN32) +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN ((void*)0) +#define GLUT_STROKE_MONO_ROMAN ((void*)1) + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 ((void*)2) +#define GLUT_BITMAP_8_BY_13 ((void*)3) +#define GLUT_BITMAP_TIMES_ROMAN_10 ((void*)4) +#define GLUT_BITMAP_TIMES_ROMAN_24 ((void*)5) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 ((void*)6) +#define GLUT_BITMAP_HELVETICA_12 ((void*)7) +#define GLUT_BITMAP_HELVETICA_18 ((void*)8) +#endif +#else +/* Stroke font opaque addresses (use constants instead in source code). */ +extern void *glutStrokeRoman; +extern void *glutStrokeMonoRoman; + +/* Stroke font constants (use these in GLUT program). */ +#define GLUT_STROKE_ROMAN (&glutStrokeRoman) +#define GLUT_STROKE_MONO_ROMAN (&glutStrokeMonoRoman) + +/* Bitmap font opaque addresses (use constants instead in source code). */ +extern void *glutBitmap9By15; +extern void *glutBitmap8By13; +extern void *glutBitmapTimesRoman10; +extern void *glutBitmapTimesRoman24; +extern void *glutBitmapHelvetica10; +extern void *glutBitmapHelvetica12; +extern void *glutBitmapHelvetica18; + +/* Bitmap font constants (use these in GLUT program). */ +#define GLUT_BITMAP_9_BY_15 (&glutBitmap9By15) +#define GLUT_BITMAP_8_BY_13 (&glutBitmap8By13) +#define GLUT_BITMAP_TIMES_ROMAN_10 (&glutBitmapTimesRoman10) +#define GLUT_BITMAP_TIMES_ROMAN_24 (&glutBitmapTimesRoman24) +#if (GLUT_API_VERSION >= 3) +#define GLUT_BITMAP_HELVETICA_10 (&glutBitmapHelvetica10) +#define GLUT_BITMAP_HELVETICA_12 (&glutBitmapHelvetica12) +#define GLUT_BITMAP_HELVETICA_18 (&glutBitmapHelvetica18) +#endif +#endif + +/* glutGet parameters. */ +#define GLUT_WINDOW_X 100 +#define GLUT_WINDOW_Y 101 +#define GLUT_WINDOW_WIDTH 102 +#define GLUT_WINDOW_HEIGHT 103 +#define GLUT_WINDOW_BUFFER_SIZE 104 +#define GLUT_WINDOW_STENCIL_SIZE 105 +#define GLUT_WINDOW_DEPTH_SIZE 106 +#define GLUT_WINDOW_RED_SIZE 107 +#define GLUT_WINDOW_GREEN_SIZE 108 +#define GLUT_WINDOW_BLUE_SIZE 109 +#define GLUT_WINDOW_ALPHA_SIZE 110 +#define GLUT_WINDOW_ACCUM_RED_SIZE 111 +#define GLUT_WINDOW_ACCUM_GREEN_SIZE 112 +#define GLUT_WINDOW_ACCUM_BLUE_SIZE 113 +#define GLUT_WINDOW_ACCUM_ALPHA_SIZE 114 +#define GLUT_WINDOW_DOUBLEBUFFER 115 +#define GLUT_WINDOW_RGBA 116 +#define GLUT_WINDOW_PARENT 117 +#define GLUT_WINDOW_NUM_CHILDREN 118 +#define GLUT_WINDOW_COLORMAP_SIZE 119 +#if (GLUT_API_VERSION >= 2) +#define GLUT_WINDOW_NUM_SAMPLES 120 +#define GLUT_WINDOW_STEREO 121 +#endif +#if (GLUT_API_VERSION >= 3) +#define GLUT_WINDOW_CURSOR 122 +#endif +#define GLUT_SCREEN_WIDTH 200 +#define GLUT_SCREEN_HEIGHT 201 +#define GLUT_SCREEN_WIDTH_MM 202 +#define GLUT_SCREEN_HEIGHT_MM 203 +#define GLUT_MENU_NUM_ITEMS 300 +#define GLUT_DISPLAY_MODE_POSSIBLE 400 +#define GLUT_INIT_WINDOW_X 500 +#define GLUT_INIT_WINDOW_Y 501 +#define GLUT_INIT_WINDOW_WIDTH 502 +#define GLUT_INIT_WINDOW_HEIGHT 503 +#define GLUT_INIT_DISPLAY_MODE 504 +#if (GLUT_API_VERSION >= 2) +#define GLUT_ELAPSED_TIME 700 +#endif +#if (GLUT_API_VERSION >= 4 || GLUT_XLIB_IMPLEMENTATION >= 13) +#define GLUT_WINDOW_FORMAT_ID 123 +#endif + +#if (GLUT_API |