diff options
-rwxr-xr-x | emcc | 15 | ||||
-rw-r--r-- | src/library_egl.js | 2 | ||||
-rw-r--r-- | src/library_gl.js | 83 | ||||
-rw-r--r-- | src/library_glut.js | 252 | ||||
-rw-r--r-- | src/preamble.js | 1 | ||||
-rw-r--r-- | src/shell.html | 3 | ||||
-rw-r--r-- | tests/cube2hash/readme.txt | 27 | ||||
-rw-r--r-- | tests/glbook/CH09_TextureWrap.png | bin | 0 -> 1812 bytes | |||
-rw-r--r-- | tests/glbook/CH10_MultiTexture.png | bin | 0 -> 59495 bytes | |||
-rw-r--r-- | tests/glbook/CH13_ParticleSystem.png | bin | 0 -> 11936 bytes | |||
-rw-r--r-- | tests/glbook/Chapter_10/MultiTexture/MultiTexture.c | 44 | ||||
-rw-r--r-- | tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c | 70 | ||||
-rw-r--r-- | tests/glbook/Chapter_9/TextureWrap/TextureWrap.c | 54 | ||||
-rw-r--r-- | tests/glbook/Makefile | 6 | ||||
-rw-r--r-- | tests/hello_world_gles.c | 19 | ||||
-rw-r--r-- | tests/hello_world_gles_deriv.c | 730 | ||||
-rwxr-xr-x | tests/runner.py | 69 | ||||
-rw-r--r-- | tools/clean_webconsole.py | 6 | ||||
-rw-r--r-- | tools/shared.py | 2 |
19 files changed, 1252 insertions, 131 deletions
@@ -534,7 +534,7 @@ try: input_files = [] has_source_inputs = False - lib_dirs = [] + lib_dirs = [shared.path_from_root('system', 'lib')] libs = [] for i in range(len(newargs)): # find input files XXX this a simple heuristic. we should really analyze based on a full understanding of gcc params, # right now we just assume that what is left contains no more |-x OPT| things @@ -542,7 +542,7 @@ try: if i > 0: prev = newargs[i-1] - if prev == '-MT': continue # ignore this gcc-style argument + if prev in ['-MT', '-install_name']: continue # ignore this gcc-style argument if arg.endswith(SOURCE_SUFFIXES + BITCODE_SUFFIXES + DYNAMICLIB_SUFFIXES + ASSEMBLY_SUFFIXES) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs newargs[i] = '' @@ -554,6 +554,16 @@ try: # this should be bitcode, make sure it is valid if arg.endswith(ASSEMBLY_SUFFIXES) or shared.Building.is_bitcode(arg): input_files.append(arg) + elif arg.endswith(STATICLIB_SUFFIXES + DYNAMICLIB_SUFFIXES): + # if it's not, and it's a library, just add it to libs to find later + l = unsuffixed_basename(arg) + for prefix in LIB_PREFIXES: + if not prefix: continue + if l.startswith(prefix): + l = l[len(prefix):] + break; + libs.append(l) + newargs[i] = '' else: print >> sys.stderr, 'emcc: %s: warning: Not valid LLVM bitcode' % arg else: @@ -564,6 +574,7 @@ try: elif arg.startswith('-l'): libs.append(arg[2:]) newargs[i] = '' + newargs = [ arg for arg in newargs if arg is not '' ] # Find library files diff --git a/src/library_egl.js b/src/library_egl.js index 6ad226f0..f1558f80 100644 --- a/src/library_egl.js +++ b/src/library_egl.js @@ -12,7 +12,7 @@ var LibraryEGL = { return 1; }, - eglMakeCurrent: function(display, surface, surface, context) { return 1 }, + eglMakeCurrent: function(display, surface, surface_, context) { return 1 }, eglSwapBuffers: function() {}, }; diff --git a/src/library_gl.js b/src/library_gl.js index 414520e0..6f99969e 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -24,6 +24,35 @@ var LibraryGL = { } return 0; }, + + // Find a token in a shader source string + findToken: function(source, token) { + function isIdentChar(ch) { + if (ch >= 48 && ch <= 57) // 0-9 + return true; + if (ch >= 65 && ch <= 90) // A-Z + return true; + if (ch >= 97 && ch <= 122) // a-z + return true; + return false; + } + var i = -1; + do { + i = source.indexOf(token, i + 1); + if (i < 0) { + break; + } + if (i > 0 && isIdentChar(source[i - 1])) { + continue; + } + i += token.length; + if (i < source.length - 1 && isIdentChar(source[i + 1])) { + continue; + } + return true; + } while (true); + return false; + }, }, glGetString: function(name_) { @@ -223,7 +252,7 @@ var LibraryGL = { case 0x8033 /* GL_UNSIGNED_SHORT_4_4_4_4 */: case 0x8034 /* GL_UNSIGNED_SHORT_5_5_5_1 */: sizePerPixel = 2; - pixels = new Uint16Array(new ArrayBuffer(Array_copy(pixels, width*height*sizePerPixel*2))); + pixels = new Uint16Array(new ArrayBuffer(Array_copy(pixels, width*height*sizePerPixel))); break; default: throw 'Invalid type (' + type + ') passed to glTexImage2D'; @@ -256,13 +285,13 @@ var LibraryGL = { default: throw 'Invalid format (' + format + ') passed to glTexSubImage2D'; } - pixels = new Uint8Array(Array_copy(pixels, (width-xoffset+1)*(height-yoffset+1)*sizePerPixel)); + pixels = new Uint8Array(Array_copy(pixels, width*height*sizePerPixel)); break; case 0x8363 /* GL_UNSIGNED_SHORT_5_6_5 */: case 0x8033 /* GL_UNSIGNED_SHORT_4_4_4_4 */: case 0x8034 /* GL_UNSIGNED_SHORT_5_5_5_1 */: sizePerPixel = 2; - pixels = new Uint16Array(new ArrayBuffer(Array_copy(pixels, (width-xoffset+1)*(height-yoffset+1)*sizePerPixel*2))); + pixels = new Uint16Array(new ArrayBuffer(Array_copy(pixels, width*height*sizePerPixel))); break; default: throw 'Invalid type (' + type + ') passed to glTexSubImage2D'; @@ -407,6 +436,33 @@ var LibraryGL = { Module.ctx.uniform4i(location, v0, v1, v2, v3); }, + glUniform1iv: function(location, count, value) { + location = GL.uniforms[location]; + value = new Int32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform1iv(location, value); + }, + + glUniform2iv: function(location, count, value) { + location = GL.uniforms[location]; + count *= 2; + value = new Int32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform2iv(location, value); + }, + + glUniform3iv: function(location, count, value) { + location = GL.uniforms[location]; + count *= 3; + value = new Int32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform3iv(location, value); + }, + + glUniform4iv: function(location, count, value) { + location = GL.uniforms[location]; + count *= 4; + value = new Int32Array(TypedArray_copy(value, count*4)); // TODO: optimize + Module.ctx.uniform4iv(location, value); + }, + glUniform1fv: function(location, count, value) { location = GL.uniforms[location]; value = new Float32Array(TypedArray_copy(value, count*4)); // TODO: optimize @@ -529,6 +585,21 @@ var LibraryGL = { } source += frag; } + // Let's see if we need to enable the standard derivatives extension + type = Module.ctx.getShaderParameter(GL.shaders[shader], 0x8B4F /* GL_SHADER_TYPE */); + if (type == 0x8B30 /* GL_FRAGMENT_SHADER */) { + if (GL.findToken(source, "dFdx") || + GL.findToken(source, "dFdy") || + GL.findToken(source, "fwidth")) { + source = "#extension GL_OES_standard_derivatives : enable\n" + source; + var extension = Module.ctx.getExtension("OES_standard_derivatives"); +#if GL_DEBUG + if (!extension) { + Module.printErr("Shader attempts to use the standard derivatives extension which is not available."); + } +#endif + } + } Module.ctx.shaderSource(GL.shaders[shader], source); }, @@ -682,10 +753,10 @@ var LibraryGL = { // Simple pass-through functions [[0, 'shadeModel fogi fogfv getError finish flush'], - [1, 'clearDepth depthFunc enable disable frontFace cullFace clear enableVertexAttribArray disableVertexAttribArray lineWidth clearStencil depthMask stencilMask stencilMaskSeparate checkFramebufferStatus generateMipmap activeTexture'], - [2, 'pixelStorei'], + [1, 'clearDepth depthFunc enable disable frontFace cullFace clear enableVertexAttribArray disableVertexAttribArray lineWidth clearStencil depthMask stencilMask stencilMaskSeparate checkFramebufferStatus generateMipmap activeTexture blendEquation'], + [2, 'pixelStorei blendFunc blendEquationSeparate'], [3, 'texParameteri texParameterf drawArrays vertexAttrib2f'], - [4, 'viewport clearColor scissor vertexAttrib3f colorMask drawElements renderbufferStorage'], + [4, 'viewport clearColor scissor vertexAttrib3f colorMask drawElements renderbufferStorage blendFuncSeparate'], [5, 'vertexAttrib4f'], [6, 'vertexAttribPointer'], [8, 'copyTexImage2D copyTexSubImage2D']].forEach(function(data) { diff --git a/src/library_glut.js b/src/library_glut.js index 0736d5ae..5d9fb672 100644 --- a/src/library_glut.js +++ b/src/library_glut.js @@ -2,6 +2,7 @@ var LibraryGLUT = { $GLUT: { initTime: null, + idleFunc: null, displayFunc: null, keyboardFunc: null, keyboardUpFunc: null, @@ -15,6 +16,14 @@ var LibraryGLUT = { lastY: 0, buttons: 0, modifiers: 0, + initWindowWidth: 256, + initWindowHeight: 256, + + savePosition: function(event) { + /* TODO maybe loop here ala http://www.quirksmode.org/js/findpos.html */ + GLUT.lastX = event['clientX'] - Module['canvas'].offsetLeft; + GLUT.lastY = event['clientY'] - Module['canvas'].offsetTop; + }, saveModifiers: function(event) { GLUT.modifiers = 0; @@ -27,9 +36,8 @@ var LibraryGLUT = { }, onMousemove: function(event) { - GLUT.lastX = event['clientX']; - GLUT.lastY = event['clientY']; - if (GLUT.buttons == 0 && GLUT.passiveMotionFunc) { + GLUT.savePosition(event); + if (GLUT.buttons == 0 && event.target == Module["canvas"] && GLUT.passiveMotionFunc) { event.preventDefault(); GLUT.saveModifiers(event); FUNCTION_TABLE[GLUT.passiveMotionFunc](GLUT.lastX, GLUT.lastY); @@ -68,9 +76,42 @@ var LibraryGLUT = { return key; }, - getASCIIKey: function(keycode) { - // TODO apply modifiers, etc - return keycode; + getASCIIKey: function(event) { + if (event['ctrlKey'] || event['altKey'] || event['metaKey']) return null; + + var keycode = event['keyCode']; + + /* The exact list is soooo hard to find in a canonical place! */ + + if (48 <= keycode && keycode <= 57) + return keycode; // numeric TODO handle shift? + if (65 <= keycode && keycode <= 90) + return event['shiftKey'] ? keycode : keycode + 32; + if (106 <= keycode && keycode <= 111) + return keycode - 106 + 42; // *,+-./ TODO handle shift? + + switch (keycode) { + case 27: // escape + case 32: // space + case 61: // equal + return keycode; + } + + var s = event['shiftKey']; + switch (keycode) { + case 186: return s ? 58 : 59; // colon / semi-colon + case 187: return s ? 43 : 61; // add / equal (these two may be wrong) + case 188: return s ? 60 : 44; // less-than / comma + case 189: return s ? 95 : 45; // dash + case 190: return s ? 62 : 46; // greater-than / period + case 191: return s ? 63 : 47; // forward slash + case 219: return s ? 123 : 91; // open bracket + case 220: return s ? 124 : 47; // back slash + case 221: return s ? 125 : 93; // close braket + case 222: return s ? 34 : 39; // single quote + } + + return null; }, onKeydown: function(event) { @@ -85,11 +126,11 @@ var LibraryGLUT = { } else { - key = GLUT.getASCIIKey(event['keyCode']); + key = GLUT.getASCIIKey(event); if( key !== null && GLUT.keyboardFunc ) { event.preventDefault(); GLUT.saveModifiers(event); - FUNCTION_TABLE[GLUT.keyboardFunc](event['keyCode'], GLUT.lastX, GLUT.lastY); + FUNCTION_TABLE[GLUT.keyboardFunc](key, GLUT.lastX, GLUT.lastY); } } } @@ -107,22 +148,24 @@ var LibraryGLUT = { } else { - key = GLUT.getASCIIKey(event['keyCode']); + key = GLUT.getASCIIKey(event); if( key !== null && GLUT.keyboardUpFunc ) { event.preventDefault (); GLUT.saveModifiers(event); - FUNCTION_TABLE[GLUT.keyboardUpFunc](event['keyCode'], GLUT.lastX, GLUT.lastY); + FUNCTION_TABLE[GLUT.keyboardUpFunc](key, GLUT.lastX, GLUT.lastY); } } } }, onMouseButtonDown: function(event){ - GLUT.lastX = event['clientX']; - GLUT.lastY = event['clientY']; + GLUT.savePosition(event); GLUT.buttons |= (1 << event['button']); - if(GLUT.mouseFunc){ + if(event.target == Module["canvas"] && GLUT.mouseFunc){ + try { + event.target.setCapture(); + } catch (e) {} event.preventDefault(); GLUT.saveModifiers(event); FUNCTION_TABLE[GLUT.mouseFunc](event['button'], 0/*GLUT_DOWN*/, GLUT.lastX, GLUT.lastY); @@ -130,8 +173,7 @@ var LibraryGLUT = { }, onMouseButtonUp: function(event){ - GLUT.lastX = event['clientX']; - GLUT.lastY = event['clientY']; + GLUT.savePosition(event); GLUT.buttons &= ~(1 << event['button']); if(GLUT.mouseFunc) { @@ -140,6 +182,48 @@ var LibraryGLUT = { FUNCTION_TABLE[GLUT.mouseFunc](event['button'], 1/*GLUT_UP*/, GLUT.lastX, GLUT.lastY); } }, + + requestFullScreen: function() { + var RFS = function() {}; + if (Module["canvas"]['requestFullscreen']) { + RFS = Module["canvas"]['requestFullscreen']; + } else if (Module["canvas"]['requestFullScreen']) { + RFS = Module["canvas"]['requestFullScreen']; + } else if (Module["canvas"]['mozRequestFullScreen']) { + RFS = Module["canvas"]['mozRequestFullScreen']; + } else if (Module["canvas"]['webkitRequestFullScreen']) { + RFS = Module["canvas"]['webkitRequestFullScreen']; + } + RFS.apply(Module["canvas"], []); + }, + + cancelFullScreen: function() { + var CFS = function() {}; + if (document['exitFullscreen']) { + CFS = document['exitFullscreen']; + } else if (document['cancelFullScreen']) { + CFS = document['cancelFullScreen']; + } else if (document['mozCancelFullScreen']) { + CFS = document['mozCancelFullScreen']; + } else if (document['webkitCancelFullScreen']) { + CFS = document['webkitCancelFullScreen']; + } + CFS.apply(document, []); + }, + + requestAnimationFrame: 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, [func]); + }, }, glutGetModifiers: function() { return GLUT.modifiers; }, @@ -147,30 +231,50 @@ var LibraryGLUT = { glutInit: function(argcp, argv) { // Ignore arguments GLUT.initTime = Date.now(); - window.addEventListener("keydown", GLUT.onKeydown, true); - window.addEventListener("keyup", GLUT.onKeyup, true); - window.addEventListener("mousemove", GLUT.onMousemove, true); - window.addEventListener("mousedown", GLUT.onMouseButtonDown, true); - window.addEventListener("mouseup", GLUT.onMouseButtonUp, true); }, glutInitWindowSize: function(width, height) { - Module['canvas'].width = width; - Module['canvas'].height = height; + Module['canvas'].width = GLUT.initWindowWidth = width; + Module['canvas'].height = GLUT.initWindowHeight = height; }, glutGet: function(type) { switch (type) { + case 100: /* GLUT_WINDOW_X */ + return 0; /* TODO */ + case 101: /* GLUT_WINDOW_Y */ + return 0; /* TODO */ + case 102: /* GLUT_WINDOW_WIDTH */ + return Module['canvas'].width; + case 103: /* GLUT_WINDOW_HEIGHT */ + return Module['canvas'].height; + case 500: /* GLUT_INIT_WINDOW_X */ + return 0; /* TODO */ + case 501: /* GLUT_INIT_WINDOW_Y */ + return 0; /* TODO */ + case 502: /* GLUT_INIT_WINDOW_WIDTH */ + return GLUT.initWindowWidth; + case 503: /* GLUT_INIT_WINDOW_HEIGHT */ + return GLUT.initWindowHeight; case 700: /* GLUT_ELAPSED_TIME */ var now = Date.now(); return now - GLUT.initTime; + default: throw "glutGet(" + type + ") not implemented yet"; } }, glutIdleFunc: function(func) { - window.setTimeout(FUNCTION_TABLE[func], 0); + var callback = function() { + if (GLUT.idleFunc) { + FUNCTION_TABLE[GLUT.idleFunc](); + window.setTimeout(callback, 0); + } + } + if (!GLUT.idleFunc) + window.setTimeout(callback, 0); + GLUT.idleFunc = func; }, glutTimerFunc: function(msec, func, value) { @@ -216,9 +320,10 @@ var LibraryGLUT = { glutCreateWindow: function(name) { #if USE_TYPED_ARRAYS try { - var ctx = Module.canvas.getContext('experimental-webgl'); + var ctx = Module["canvas"].getContext('experimental-webgl'); if (!ctx) throw 'Could not create canvas :('; #if GL_DEBUG + // Useful to debug native webgl apps: var Module = { printErr: function(x) { console.log(x) } }; var wrapper = {}; wrapper.objectMap = new WeakMap(); wrapper.objectCounter = 1; @@ -229,7 +334,31 @@ var LibraryGLUT = { wrapper[prop] = function() { var printArgs = Array.prototype.slice.call(arguments).map(function(arg) { if (wrapper.objectMap[arg]) return '<' + arg + '|' + wrapper.objectMap[arg] + '>'; - if (arg.subarray) return '{' + arg + '|' + arg.length /*+ '|' + Array.prototype.slice.call(arg).toString().replace(/,/g, ', ')*/ + '}'; + if (arg.toString() == '[object HTMLImageElement]') { + return arg + '\n\n'; + } + if (arg.byteLength) { + var buf = new ArrayBuffer(32); + var i8buf = new Int8Array(buf); + var f32buf = new Float32Array(buf); + switch(arg.toString()) { + case '[object Uint8Array]': + i8buf.set(arg.subarray(0, 32)); + break; + case '[object Float32Array]': + f32buf.set(arg.subarray(0, 5)); + break; + default: + alert('unknown array for debugging: ' + arg); + throw 'see alert'; + } + var ret = '{' + arg.byteLength + ':\n'; + var arr = Array.prototype.slice.call(i8buf); + ret += 'i8:' + arr.toString().replace(/,/g, ',') + '\n'; + arr = Array.prototype.slice.call(f32buf, 0, 8); + ret += 'f32:' + arr.toString().replace(/,/g, ',') + '}'; + return ret; + } return arg; }); Module.printErr('[gl_f:' + prop + ':' + printArgs + ']'); @@ -264,7 +393,7 @@ var LibraryGLUT = { #endif // 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"; + Module["canvas"].style.backgroundColor = "black"; } catch (e) { Module.print('(canvas not available)'); } @@ -274,33 +403,70 @@ var LibraryGLUT = { return 1; }, + glutReshapeWindow__deps: ['$GLUT', 'glutPostRedisplay'], + glutReshapeWindow: function(width, height) { + GLUT.cancelFullScreen(); + Module['canvas'].width = width; + Module['canvas'].height = height; + if (GLUT.reshapeFunc) { + FUNCTION_TABLE[GLUT.reshapeFunc](width, height); + } + _glutPostRedisplay(); + }, + + glutPositionWindow__deps: ['$GLUT', 'glutPostRedisplay'], + glutPositionWindow: function(x, y) { + GLUT.cancelFullScreen(); + /* TODO */ + _glutPostRedisplay(); + }, + + glutFullScreen__deps: ['$GLUT', 'glutPostRedisplay'], + glutFullScreen: function() { + var width = screen["width"]; + var height = screen["height"]; + /* Can't call _glutReshapeWindow as that requests cancelling fullscreen. */ + Module['canvas'].width = width; + Module['canvas'].height = height; + if (GLUT.reshapeFunc) { + FUNCTION_TABLE[GLUT.reshapeFunc](width, height); + } + GLUT.requestFullScreen(); + window.setTimeout(function() { + _glutPostRedisplay(); + }, 0); + }, + glutInitDisplayMode: function(mode) {}, glutSwapBuffers: function() {}, glutPostRedisplay: function() { if (GLUT.displayFunc) { - 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_TABLE[GLUT.displayFunc]]); + GLUT.requestAnimationFrame(FUNCTION_TABLE[GLUT.displayFunc]); } }, - glutMainLoop__deps: ['$GLUT', 'glutPostRedisplay'], + glutMainLoop__deps: ['$GLUT', 'glutReshapeWindow', 'glutPostRedisplay'], glutMainLoop: function() { - if (GLUT.reshapeFunc) { - FUNCTION_TABLE[GLUT.reshapeFunc](Module['canvas'].width, - Module['canvas'].height); - } + + window.addEventListener("keydown", GLUT.onKeydown, true); + window.addEventListener("keyup", GLUT.onKeyup, true); + window.addEventListener("mousemove", GLUT.onMousemove, true); + window.addEventListener("mousedown", GLUT.onMouseButtonDown, true); + window.addEventListener("mouseup", GLUT.onMouseButtonUp, true); + + __ATEXIT__.push({ func: function() { + window.removeEventListener("keydown", GLUT.onKeydown, true); + window.removeEventListener("keyup", GLUT.onKeyup, true); + window.removeEventListener("mousemove", GLUT.onMousemove, true); + window.removeEventListener("mousedown", GLUT.onMouseButtonDown, true); + window.removeEventListener("mouseup", GLUT.onMouseButtonUp, true); + Module["canvas"].width = Module["canvas"].height = 1; + } }); + + _glutReshapeWindow(Module['canvas'].width, Module['canvas'].height); _glutPostRedisplay(); - throw 'GLUT mainloop should never return'; + throw 'GLUT mainloop called, simulating infinite loop by throwing so we get right into the JS event loop'; }, }; diff --git a/src/preamble.js b/src/preamble.js index c88a4671..39412bc3 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -368,6 +368,7 @@ function cwrap(ident, returnType, argTypes) { return ccall(ident, returnType, argTypes, Array.prototype.slice.call(arguments)); } } +Module["cwrap"] = cwrap; // Sets a value in memory in a dynamic way at run-time. Uses the // type data. This is the same as makeSetValue, except that diff --git a/src/shell.html b/src/shell.html index 4c7b2147..37509889 100644 --- a/src/shell.html +++ b/src/shell.html @@ -4,7 +4,8 @@ <title>Emscripten-Generated Code</title> <body> <center> - <canvas id='canvas' width='256' height='256'></canvas> + <canvas id='canvas' width='256' height='256' style="border: 1px solid black" + oncontextmenu="event.preventDefault()"></canvas> <hr> <textarea id="output" style="font-family: monospace; width: 80%" rows="8"></textarea> <hr> diff --git a/tests/cube2hash/readme.txt b/tests/cube2hash/readme.txt new file mode 100644 index 00000000..6eb129c2 --- /dev/null +++ b/tests/cube2hash/readme.txt @@ -0,0 +1,27 @@ +This directory contains zlib code (c) the Cube 2/Sauerbraten project. +http://sauerbraten.org/ + +LICENSE +======= + +Sauerbraten game engine source code, any release. + +Copyright (C) 2001-2009 Wouter van Oortmerssen, Lee Salzman, Mike Dysart, Robert Pointon, and Quinton Reeves + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + + diff --git a/tests/glbook/CH09_TextureWrap.png b/tests/glbook/CH09_TextureWrap.png Binary files differnew file mode 100644 index 00000000..3367e254 --- /dev/null +++ b/tests/glbook/CH09_TextureWrap.png diff --git a/tests/glbook/CH10_MultiTexture.png b/tests/glbook/CH10_MultiTexture.png Binary files differnew file mode 100644 index 00000000..8e006eb3 --- /dev/null +++ b/tests/glbook/CH10_MultiTexture.png diff --git a/tests/glbook/CH13_ParticleSystem.png b/tests/glbook/CH13_ParticleSystem.png Binary files differnew file mode 100644 index 00000000..39b9af0a --- /dev/null +++ b/tests/glbook/CH13_ParticleSystem.png diff --git a/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c b/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c index 5324ad92..61bda608 100644 --- a/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c +++ b/tests/glbook/Chapter_10/MultiTexture/MultiTexture.c @@ -33,6 +33,8 @@ typedef struct GLuint baseMapTexId;
GLuint lightMapTexId;
+ GLuint vertexObject, indexObject;
+
} UserData;
@@ -117,7 +119,27 @@ int Init ( ESContext *esContext ) if ( userData->baseMapTexId == 0 || userData->lightMapTexId == 0 )
return FALSE;
- glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ GLfloat vVertices[] = { -0.5, 0.5, 0.0, // Position 0
+ 0.0, 0.0, // TexCoord 0
+ -0.5, -0.5, 0.0, // Position 1
+ 0.0, 1.0, // TexCoord 1
+ 0.5, -0.5, 0.0, // Position 2
+ 1.0, 1.0, // TexCoord 2
+ 0.5, 0.5, 0.0, // Position 3
+ 1.0, 0.0 // TexCoord 3
+ };
+ GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
+
+ glGenBuffers(1, &userData->vertexObject);
+ glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject );
+ glBufferData ( GL_ARRAY_BUFFER, 5 * 4 * 4, vVertices, GL_STATIC_DRAW );
+
+ glGenBuffers(1, &userData->indexObject);
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject );
+ glBufferData ( GL_ELEMENT_ARRAY_BUFFER, 6 * 2, indices, GL_STATIC_DRAW );
+
+ glClearColor ( 0.0, 0.0, 0.0, 1.0 );
+
return TRUE;
}
@@ -127,17 +149,7 @@ int Init ( ESContext *esContext ) void Draw ( ESContext *esContext )
{
UserData *userData = esContext->userData;
- GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0
- 0.0f, 0.0f, // TexCoord 0
- -0.5f, -0.5f, 0.0f, // Position 1
- 0.0f, 1.0f, // TexCoord 1
- 0.5f, -0.5f, 0.0f, // Position 2
- 1.0f, 1.0f, // TexCoord 2
- 0.5f, 0.5f, 0.0f, // Position 3
- 1.0f, 0.0f // TexCoord 3
- };
- GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
-
+
// Set the viewport
glViewport ( 0, 0, esContext->width, esContext->height );
@@ -148,11 +160,12 @@ void Draw ( ESContext *esContext ) glUseProgram ( userData->programObject );
// Load the vertex position
+ glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject );
glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
- GL_FALSE, 5 * sizeof(GLfloat), vVertices );
+ GL_FALSE, 5 * sizeof(GLfloat), 0 );
// Load the texture coordinate
glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
- GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
+ GL_FALSE, 5 * sizeof(GLfloat), 3 * sizeof(GLfloat) );
glEnableVertexAttribArray ( userData->positionLoc );
glEnableVertexAttribArray ( userData->texCoordLoc );
@@ -171,7 +184,8 @@ void Draw ( ESContext *esContext ) // Set the light map sampler to texture unit 1
glUniform1i ( userData->lightMapLoc, 1 );
- glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
+ glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject );
+ glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 );
eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
}
diff --git a/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c index 378d05a7..f48e871a 100644 --- a/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c +++ b/tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c @@ -17,9 +17,16 @@ #include <math.h>
#include "esUtil.h"
-#define NUM_PARTICLES 1000
+#define NUM_PARTICLES 2000
#define PARTICLE_SIZE 7
+int randomTemp = 8765;
+float myrandom() {
+ int curr = randomTemp;
+ randomTemp = (1140671485 * randomTemp + 12820163) % 4294967296;
+ return ((float)curr) / 4294967296;
+}
+
typedef struct
{
// Handle to a program object
@@ -40,11 +47,12 @@ typedef struct GLuint textureId;
// Particle vertex data
- float particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
+ GLfloat particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
// Current time
float time;
+ GLuint vertexObject;
} UserData;
///
@@ -136,29 +144,31 @@ int Init ( ESContext *esContext ) userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
- glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
+ glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
// Fill in particle data array
- srand ( 0 );
for ( i = 0; i < NUM_PARTICLES; i++ )
{
- float *particleData = &userData->particleData[i * PARTICLE_SIZE];
+ GLfloat *particleData = &userData->particleData[i * PARTICLE_SIZE];
// Lifetime of particle
- (*particleData++) = ( (float)(rand() % 10000) / 10000.0f );
+ (*particleData++) = myrandom();
// End position of particle
- (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
- (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
- (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
+ (*particleData++) = myrandom() * 2 - 1.0f;
+ (*particleData++) = myrandom() * 2 - 1.0f;
+ (*particleData++) = myrandom() * 2 - 1.0f;
// Start position of particle
- (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
- (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
- (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
-
+ (*particleData++) = myrandom() * 0.25 - 0.125f;
+ (*particleData++) = myrandom() * 0.25 - 0.125f;
+ (*particleData++) = myrandom() * 0.25 - 0.125f;
}
+ glGenBuffers(1, &userData->vertexObject);
+ glBindBuffer( GL_ARRAY_BUFFER, userData->vertexObject );
+ glBufferData( GL_ARRAY_BUFFER, NUM_PARTICLES * PARTICLE_SIZE * 4, userData->particleData, GL_STATIC_DRAW );
+
// Initialize time to cause reset on first update
userData->time = 1.0f;
@@ -176,6 +186,7 @@ int Init ( ESContext *esContext ) //
void Update ( ESContext *esContext, float deltaTime )
{
+// deltaTime = 0.1;
UserData *userData = esContext->userData;
userData->time += deltaTime;
@@ -188,17 +199,17 @@ void Update ( ESContext *esContext, float deltaTime ) userData->time = 0.0f;
// Pick a new start location and color
- centerPos[0] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
- centerPos[1] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
- centerPos[2] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
+ centerPos[0] = myrandom() - 0.5f;
+ centerPos[1] = myrandom() - 0.5f;
+ centerPos[2] = myrandom() - 0.5f;
glUniform3fv ( userData->centerPositionLoc, 1, ¢erPos[0] );
// Random color
- color[0] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
- color[1] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
- color[2] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
- color[3] = 0.5;
+ color[0] = myrandom() * 0.5 + 0.5f;
+ color[1] = myrandom() * 0.5 + 0.5f;
+ color[2] = myrandom() * 0.5 + 0.5f;
+ color[3] = 1.0;
glUniform4fv ( userData->colorLoc, 1, &color[0] );
}
@@ -224,17 +235,18 @@ void Draw ( ESContext *esContext ) glUseProgram ( userData->programObject );
// Load the vertex attributes
+ glBindBuffer( GL_ARRAY_BUFFER, userData->vertexObject );
glVertexAttribPointer ( userData->lifetimeLoc, 1, GL_FLOAT,
GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
- userData->particleData );
+ 0 );
glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
- &userData->particleData[1] );
+ 4 );
glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
- &userData->particleData[4] );
+ 4 * 4 );
glEnableVertexAttribArray ( userData->lifetimeLoc );
@@ -247,11 +259,13 @@ void Draw ( ESContext *esContext ) // Bind the texture
glActiveTexture ( GL_TEXTURE0 );
glBindTexture ( GL_TEXTURE_2D, userData->textureId );
- glEnable ( GL_TEXTURE_2D );
+ //glEnable ( GL_TEXTURE_2D );
// Set the sampler texture unit to 0
glUniform1i ( userData->samplerLoc, 0 );
+ Update ( esContext, 133 * 0.001125 );
+
glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
@@ -280,15 +294,17 @@ int main ( int argc, char *argv[] ) esInitContext ( &esContext );
esContext.userData = &userData;
- esCreateWindow ( &esContext, "ParticleSystem", 640, 480, ES_WINDOW_RGB );
+ esCreateWindow ( &esContext, "ParticleSystem", 320, 240, ES_WINDOW_RGB );
if ( !Init ( &esContext ) )
return 0;
esRegisterDrawFunc ( &esContext, Draw );
- esRegisterUpdateFunc ( &esContext, Update );
+// esRegisterUpdateFunc ( &esContext, Update );
- esMainLoop ( &esContext );
+ Draw (&esContext);
+ Draw (&esContext);
+ //esMainLoop ( &esContext );
ShutDown ( &esContext );
}
diff --git a/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c b/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c index fe22282f..30f39444 100644 --- a/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c +++ b/tests/glbook/Chapter_9/TextureWrap/TextureWrap.c @@ -34,6 +34,8 @@ typedef struct // Texture handle GLuint textureId; + GLuint vertexObject, indexObject; + } UserData; /// @@ -88,6 +90,9 @@ GLuint CreateTexture2D( ) if ( pixels == NULL ) return 0; + // Use tightly packed data + glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); + // Generate a texture object glGenTextures ( 1, &textureId ); @@ -152,7 +157,28 @@ int Init ( ESContext *esContext ) // Load the texture userData->textureId = CreateTexture2D (); - glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + // Setup the vertex data + GLfloat vVertices[] = { -0.3, 0.3, 0.0, 1.0, // Position 0 + -1.0, -1.0, // TexCoord 0 + -0.3, -0.3, 0.0, 1.0, // Position 1 + -1.0, 2.0, // TexCoord 1 + 0.3, -0.3, 0.0, 1.0, // Position 2 + 2.0, 2.0, // TexCoord 2 + 0.3, 0.3, 0.0, 1.0, // Position 3 + 2.0, -1.0 // TexCoord 3 + }; + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + glGenBuffers(1, &userData->vertexObject); + glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject ); + glBufferData ( GL_ARRAY_BUFFER, 6 * 4 * 4, vVertices, GL_STATIC_DRAW ); + + glGenBuffers(1, &userData->indexObject); + glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject ); + glBufferData ( GL_ELEMENT_ARRAY_BUFFER, 6 * 2, indices, GL_STATIC_DRAW ); + + glClearColor ( 0.0, 0.0, 0.0, 1.0 ); + return GL_TRUE; } @@ -162,17 +188,7 @@ int Init ( ESContext *esContext ) void Draw ( ESContext *esContext ) { UserData *userData = esContext->userData; - GLfloat vVertices[] = { -0.3f, 0.3f, 0.0f, 1.0f, // Position 0 - -1.0f, -1.0f, // TexCoord 0 - -0.3f, -0.3f, 0.0f, 1.0f, // Position 1 - -1.0f, 2.0f, // TexCoord 1 - 0.3f, -0.3f, 0.0f, 1.0f, // Position 2 - 2.0f, 2.0f, // TexCoord 2 - 0.3f, 0.3f, 0.0f, 1.0f, // Position 3 - 2.0f, -1.0f // TexCoord 3 - }; - GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; - + // Set the viewport glViewport ( 0, 0, esContext->width, esContext->height ); @@ -183,11 +199,12 @@ void Draw ( ESContext *esContext ) glUseProgram ( userData->programObject ); // Load the vertex position + glBindBuffer ( GL_ARRAY_BUFFER, userData->vertexObject ); glVertexAttribPointer ( userData->positionLoc, 4, GL_FLOAT, - GL_FALSE, 6 * sizeof(GLfloat), vVertices ); + GL_FALSE, 6 * sizeof(GLfloat), 0 ); // Load the texture coordinate glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, - GL_FALSE, 6 * sizeof(GLfloat), &vVertices[4] ); + GL_FALSE, 6 * sizeof(GLfloat), 4 * sizeof(GLfloat) ); glEnableVertexAttribArray ( userData->positionLoc ); glEnableVertexAttribArray ( userData->texCoordLoc ); @@ -203,19 +220,20 @@ void Draw ( ESContext *esContext ) glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); glUniform1f ( userData->offsetLoc, -0.7f ); - glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->indexObject ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 ); // Draw quad with clamp to edge wrap mode glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glUniform1f ( userData->offsetLoc, 0.0f ); - glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 ); // Draw quad with mirrored repeat glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT ); glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT ); glUniform1f ( userData->offsetLoc, 0.7f ); - glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0 ); } @@ -243,7 +261,7 @@ int main ( int argc, char *argv[] ) esInitContext ( &esContext ); esContext.userData = &userData; - esCreateWindow ( &esContext, "MipMap 2D", 640, 480, ES_WINDOW_RGB ); + esCreateWindow ( &esContext, "MipMap 2D", 320, 240, ES_WINDOW_RGB ); if ( !Init ( &esContext ) ) return 0; diff --git a/tests/glbook/Makefile b/tests/glbook/Makefile index df8b1615..62cffedf 100644 --- a/tests/glbook/Makefile +++ b/tests/glbook/Makefile @@ -27,11 +27,11 @@ all: ./Chapter_2/Hello_Triangle/CH02_HelloTriangle.bc \ ./Chapter_9/Simple_Texture2D/CH09_SimpleTexture2D.bc \ ./Chapter_9/MipMap2D/CH09_MipMap2D.bc \ ./Chapter_9/Simple_TextureCubemap/CH09_TextureCubemap.bc \ -# ./Chapter_9/TextureWrap/CH09_TextureWrap.bc \ -# ./Chapter_10/MultiTexture/CH10_MultiTexture.bc \ + ./Chapter_9/TextureWrap/CH09_TextureWrap.bc \ + ./Chapter_10/MultiTexture/CH10_MultiTexture.bc \ + ./Chapter_13/ParticleSystem/CH13_ParticleSystem.bc # ./Chapter_11/Multisample/CH11_Multisample.bc \ # ./Chapter_11/Stencil_Test/CH11_Stencil_Test.bc \ -# ./Chapter_13/ParticleSystem/CH13_ParticleSystem.bc clean: find . -name "CH??_*" | xargs rm -f diff --git a/tests/hello_world_gles.c b/tests/hello_world_gles.c index 4f2cb45c..6f7a4324 100644 --- a/tests/hello_world_gles.c +++ b/tests/hello_world_gles.c @@ -46,17 +46,28 @@ #include <string.h> #include <sys/time.h> #include <unistd.h> +#ifdef __APPLE__ +#include <OpenGL/gl.h> +#include <Glut/glut.h> +#else #include <GL/gl.h> #include <GL/glut.h> - -#ifndef HAVE_BUILTIN_SINCOS -#include "sincos.h" #endif #define STRIPS_PER_TOOTH 7 #define VERTICES_PER_TOOTH 34 #define GEAR_VERTEX_STRIDE 6 +#ifndef HAVE_BUILTIN_SINCOS +#define sincos _sincos +static void +sincos (double a, double *s, double *c) +{ + *s = sin (a); + *c = cos (a); +} +#endif + /** * Struct describing the vertices in triangle strip */ @@ -715,7 +726,7 @@ main(int argc, char *argv[]) glutCreateWindow("es2gears"); /* Set up glut callback functions */ - gears_idle(); + glutIdleFunc (gears_idle); glutReshapeFunc(gears_reshape); glutDisplayFunc(gears_draw); glutSpecialFunc(gears_special); diff --git a/tests/hello_world_gles_deriv.c b/tests/hello_world_gles_deriv.c new file mode 100644 index 00000000..2e0f0664 --- /dev/null +++ b/tests/hello_world_gles_deriv.c @@ -0,0 +1,730 @@ +/* + * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * Ported to GLES2. + * Kristian Høgsberg <krh@bitplanet.net> + * May 3, 2010 + * + * Improve GLES2 port: + * * Refactor gear drawing. + * * Use correct normals for surfaces. + * * Improve shader. + * * Use perspective projection transformation. + * * Add FPS count. + * * Add comments. + * Alexandros Frantzis <alexandros.frantzis@linaro.org> + * Jul 13, 2010 + */ + +#define GL_GLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES + +#define _GNU_SOURCE + +#include <math.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/time.h> +#include <unistd.h> +#include <GL/gl.h> +#include <GL/glut.h> + +#ifndef HAVE_BUILTIN_SINCOS +#include "sincos.h" +#endif + +#define STRIPS_PER_TOOTH 7 +#define VERTICES_PER_TOOTH 34 +#define GEAR_VERTEX_STRIDE 6 + +/** + * Struct describing the vertices in triangle strip + */ +struct vertex_strip { + /** The first vertex in the strip */ + GLint first; + /** The number of consecutive vertices in the strip after the first */ + GLint count; +}; + +/* Each vertex consist of GEAR_VERTEX_STRIDE GLfloat attributes */ +typedef GLfloat GearVertex[GEAR_VERTEX_STRIDE]; + +/** + * Struct representing a gear. + */ +struct gear { + /** The array of vertices comprising the gear */ + GearVertex *vertices; + /** The number of vertices comprising the gear */ + int nvertices; + /** The array of triangle strips comprising the gear */ + struct vertex_strip *strips; + /** The number of triangle strips comprising the gear */ + int nstrips; + /** The Vertex Buffer Object holding the vertices in the graphics card */ + GLuint vbo; +}; + +/** The view rotation [x, y, z] */ +static GLfloat view_rot[3] = { 20.0, 30.0, 0.0 }; +/** The gears */ +static struct gear *gear1, *gear2, *gear3; +/** The current gear rotation angle */ +static GLfloat angle = 0.0; +/** The location of the shader uniforms */ +static GLuint ModelViewProjectionMatrix_location, + NormalMatrix_location, + LightSourcePosition_location, + MaterialColor_location; +/** The projection matrix */ +static GLfloat ProjectionMatrix[16]; +/** The direction of the directional light for the scene */ +static const GLfloat LightSourcePosition[4] = { 5.0, 5.0, 10.0, 1.0}; + +/** + * Fills a gear vertex. + * + * @param v the vertex to fill + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coortinate + * @param n pointer to the normal table + * + * @return the operation error code + */ +static GearVertex * +vert(GearVertex *v, GLfloat x, GLfloat y, GLfloat z, GLfloat n[3]) +{ + v[0][0] = x; + v[0][1] = y; + v[0][2] = z; + v[0][3] = n[0]; + v[0][4] = n[1]; + v[0][5] = n[2]; + + return v + 1; +} + +/** + * Create a gear wheel. + * + * @param inner_radius radius of hole at center + * @param outer_radius radius at center of teeth + * @param width width of gear + * @param teeth number of teeth + * @param tooth_depth depth of tooth + * + * @return pointer to the constructed struct gear + */ +static struct gear * +create_gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, + GLint teeth, GLfloat tooth_depth) +{ + GLfloat r0, r1, r2; + GLfloat da; + GearVertex *v; + struct gear *gear; + double s[5], c[5]; + GLfloat normal[3]; + int cur_strip = 0; + int i; + + /* Allocate memory for the gear */ + gear = malloc(sizeof *gear); + if (gear == NULL) + return NULL; + + /* Calculate the radii used in the gear */ + r0 = inner_radius; + r1 = outer_radius - tooth_depth / 2.0; + r2 = outer_radius + tooth_depth / 2.0; + + da = 2.0 * M_PI / teeth / 4.0; + + /* Allocate memory for the triangle strip information */ + gear->nstrips = STRIPS_PER_TOOTH * teeth; + gear->strips = calloc(gear->nstrips, sizeof (*gear->strips)); + + /* Allocate memory for the vertices */ + gear->vertices = calloc(VERTICES_PER_TOOTH * teeth, sizeof(*gear->vertices)); + v = gear->vertices; + + for (i = 0; i < teeth; i++) { + /* Calculate needed sin/cos for varius angles */ + sincos(i * 2.0 * M_PI / teeth, &s[0], &c[0]); + sincos(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]); + sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]); + sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]); + sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]); + + /* A set of macros for making the creation of the gears easier */ +#define GEAR_POINT(r, da) { (r) * c[(da)], (r) * s[(da)] } +#define SET_NORMAL(x, y, z) do { \ + normal[0] = (x); normal[1] = (y); normal[2] = (z); \ +} while(0) + +#define GEAR_VERT(v, point, sign) vert((v), p[(point)].x, p[(point)].y, (sign) * width * 0.5, normal) + +#define START_STRIP do { \ + gear->strips[cur_strip].first = v - gear->vertices; \ +} while(0); + +#define END_STRIP do { \ + int _tmp = (v - gear->vertices); \ + gear->strips[cur_strip].count = _tmp - gear->strips[cur_strip].first; \ + cur_strip++; \ +} while (0) + +#define QUAD_WITH_NORMAL(p1, p2) do { \ + SET_NORMAL((p[(p1)].y - p[(p2)].y), -(p[(p1)].x - p[(p2)].x), 0); \ + v = GEAR_VERT(v, (p1), -1); \ + v = GEAR_VERT(v, (p1), 1); \ + v = GEAR_VERT(v, (p2), -1); \ + v = GEAR_VERT(v, (p2), 1); \ +} while(0) + + struct point { + GLfloat x; + GLfloat y; + }; + + /* Create the 7 points (only x,y coords) used to draw a tooth */ + struct point p[7] = { + GEAR_POINT(r2, 1), // 0 + GEAR_POINT(r2, 2), // 1 + GEAR_POINT(r1, 0), // 2 + GEAR_POINT(r1, 3), // 3 + GEAR_POINT(r0, 0), // 4 + GEAR_POINT(r1, 4), // 5 + GEAR_POINT(r0, 4), // 6 + }; + + /* Front face */ + START_STRIP; + SET_NORMAL(0, 0, 1.0); + v = GEAR_VERT(v, 0, +1); + v = GEAR_VERT(v, 1, +1); + v = GEAR_VERT(v, 2, +1); + v = GEAR_VERT(v, 3, +1); + v = GEAR_VERT(v, 4, +1); + v = GEAR_VERT(v, 5, +1); + v = GEAR_VERT(v, 6, +1); + END_STRIP; + + /* Inner face */ + START_STRIP; + QUAD_WITH_NORMAL(4, 6); + END_STRIP; + + /* Back face */ + START_STRIP; + SET_NORMAL(0, 0, -1.0); + v = GEAR_VERT(v, 6, -1); + v = GEAR_VERT(v, 5, -1); + v = GEAR_VERT(v, 4, -1); + v = GEAR_VERT(v, 3, -1); + v = GEAR_VERT(v, 2, -1); + v = GEAR_VERT(v, 1, -1); + v = GEAR_VERT(v, 0, -1); + END_STRIP; + + /* Outer face */ + START_STRIP; + QUAD_WITH_NORMAL(0, 2); + END_STRIP; + + START_STRIP; + QUAD_WITH_NORMAL(1, 0); + END_STRIP; + + START_STRIP; + QUAD_WITH_NORMAL(3, 1); + END_STRIP; + + START_STRIP; + QUAD_WITH_NORMAL(5, 3); + END_STRIP; + } + + gear->nvertices = (v - gear->vertices); + + /* Store the vertices in a vertex buffer object (VBO) */ + glGenBuffers(1, &gear->vbo); + glBindBuffer(GL_ARRAY_BUFFER, gear->vbo); + glBufferData(GL_ARRAY_BUFFER, gear->nvertices * sizeof(GearVertex), + gear->vertices, GL_STATIC_DRAW); + + return gear; +} + +/** + * Multiplies two 4x4 matrices. + * + * The result is stored in matrix m. + * + * @param m the first matrix to multiply + * @param n the second matrix to multiply + */ +static void +multiply(GLfloat *m, const GLfloat *n) +{ + GLfloat tmp[16]; + const GLfloat *row, *column; + div_t d; + int i, j; + + for (i = 0; i < 16; i++) { + tmp[i] = 0; + d = div(i, 4); + row = n + d.quot * 4; + column = m + d.rem; + for (j = 0; j < 4; j++) + tmp[i] += row[j] * column[j * 4]; + } + memcpy(m, &tmp, sizeof tmp); +} + +/** + * Rotates a 4x4 matrix. + * + * @param[in,out] m the matrix to rotate + * @param angle the angle to rotate + * @param x the x component of the direction to rotate to + * @param y the y component of the direction to rotate to + * @param z the z component of the direction to rotate to + */ +static void +rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) +{ + double s, c; + + sincos(angle, &s, &c); + GLfloat r[16] = { + x * x * (1 - c) + c, y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0, + x * y * (1 - c) - z * s, y * y * (1 - c) + c, y * z * (1 - c) + x * s, 0, + x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c, 0, + 0, 0, 0, 1 + }; + + multiply(m, r); +} + + +/** + * Translates a 4x4 matrix. + * + * @param[in,out] m the matrix to translate + * @param x the x component of the direction to translate to + * @param y the y component of the direction to translate to + * @param z the z component of the direction to translate to + */ +static void +translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z) +{ + GLfloat t[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 }; + + multiply(m, t); +} + +/** + * Creates an identity 4x4 matrix. + * + * @param m the matrix make an identity matrix + */ +static void +identity(GLfloat *m) +{ + GLfloat t[16] = { + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, + }; + + memcpy(m, t, sizeof(t)); +} + +/** + * Transposes a 4x4 matrix. + * + * @param m the matrix to transpose + */ +static void +transpose(GLfloat *m) +{ + GLfloat t[16] = { + m[0], m[4], m[8], m[12], + m[1], m[5], m[9], m[13], + m[2], m[6], m[10], m[14], + m[3], m[7], m[11], m[15]}; + + memcpy(m, t, sizeof(t)); +} + +/** + * Inverts a 4x4 matrix. + * + * This function can currently handle only pure translation-rotation matrices. + * Read http://www.gamedev.net/community/forums/topic.asp?topic_id=425118 + * for an explanation. + */ +static void +invert(GLfloat *m) +{ + GLfloat t[16]; + identity(t); + + // Extract and invert the translation part 't'. The inverse of a + // translation matrix can be calculated by negating the translation + // coordinates. + t[12] = -m[12]; t[13] = -m[13]; t[14] = -m[14]; + + // Invert the rotation part 'r'. The inverse of a rotation matrix is + // equal to its transpose. + m[12] = m[13] = m[14] = 0; + transpose(m); + + // inv(m) = inv(r) * inv(t) + multiply(m, t); +} + +/** + * Calculate a perspective projection transformation. + * + * @param m the matrix to save the transformation in + * @param fovy the field of view in the y direction + * @param aspect the view aspect ratio + * @param zNear the near clipping plane + * @param zFar the far clipping plane + */ +void perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) +{ + GLfloat tmp[16]; + identity(tmp); + + double sine, cosine, cotangent, deltaZ; + GLfloat radians = fovy / 2 * M_PI / 180; + + deltaZ = zFar - zNear; + sincos(radians, &sine, &cosine); + + if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) + return; + + cotangent = cosine / sine; + + tmp[0] = cotangent / aspect; + tmp[5] = cotangent; + tmp[10] = -(zFar + zNear) / deltaZ; + tmp[11] = -1; + tmp[14] = -2 * zNear * zFar / deltaZ; + tmp[15] = 0; + + memcpy(m, tmp, sizeof(tmp)); +} + +/** + * Draws a gear. + * + * @param gear the gear to draw + * @param transform the current transformation matrix + * @param x the x position to draw the gear at + * @param y the y position to draw the gear at + * @param angle the rotation angle of the gear + * @param color the color of the gear + */ +static void +draw_gear(struct gear *gear, GLfloat *transform, + GLfloat x, GLfloat y, GLfloat angle, const GLfloat color[4]) +{ + GLfloat model_view[16]; + GLfloat normal_matrix[16]; + GLfloat model_view_projection[16]; + + /* Translate and rotate the gear */ + memcpy(model_view, transform, sizeof (model_view)); + translate(model_view, x, y, 0); + rotate(model_view, 2 * M_PI * angle / 360.0, 0, 0, 1); + + /* Create and set the ModelViewProjectionMatrix */ + memcpy(model_view_projection, ProjectionMatrix, sizeof(model_view_projection)); + multiply(model_view_projection, model_view); + + glUniformMatrix4fv(ModelViewProjectionMatrix_location, 1, GL_FALSE, + model_view_projection); + + /* + * Create and set the NormalMatrix. It's the inverse transpose of the + * ModelView matrix. + */ + memcpy(normal_matrix, model_view, sizeof (normal_matrix)); + invert(normal_matrix); + transpose(normal_matrix); + glUniformMatrix4fv(NormalMatrix_location, 1, GL_FALSE, normal_matrix); + + /* Set the gear color */ + glUniform4fv(MaterialColor_location, 1, color); + + /* Set the vertex buffer object to use */ + glBindBuffer(GL_ARRAY_BUFFER, gear->vbo); + + /* Set up the position of the attributes in the vertex buffer object */ + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, + 6 * sizeof(GLfloat), NULL); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, + 6 * sizeof(GLfloat), (GLfloat *) 0 + 3); + + /* Enable the attributes */ + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + + /* Draw the triangle strips that comprise the gear */ + int n; + for (n = 0; n < gear->nstrips; n++) + glDrawArrays(GL_TRIANGLE_STRIP, gear->strips[n].first, gear->strips[n].count); + + /* Disable the attributes */ + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(0); +} + +/** + * Draws the gears. + */ +static void +gears_draw(void) +{ + const static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; + const static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; + const static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; + GLfloat transform[16]; + identity(transform); + + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* Translate and rotate the view */ + translate(transform, 0, 0, -20); + rotate(transform, 2 * M_PI * view_rot[0] / 360.0, 1, 0, 0); + rotate(transform, 2 * M_PI * view_rot[1] / 360.0, 0, 1, 0); + rotate(transform, 2 * M_PI * view_rot[2] / 360.0, 0, 0, 1); + + /* Draw the gears */ + draw_gear(gear1, transform, -3.0, -2.0, angle, red); + draw_gear(gear2, transform, 3.1, -2.0, -2 * angle - 9.0, green); + draw_gear(gear3, transform, -3.1, 4.2, -2 * angle - 25.0, blue); + + glutSwapBuffers(); +} + +/** + * Handles a new window size or exposure. + * + * @param width the window width + * @param height the window height + */ +static void +gears_reshape(int width, int height) +{ + /* Update the projection matrix */ + perspective(ProjectionMatrix, 60.0, width / (float)height, 1.0, 1024.0); + + /* Set the viewport */ + glViewport(0, 0, (GLint) width, (GLint) height); +} + +/** + * Handles special glut events. + * + * @param special the event to handle. + */ +static void +gears_special(int special, int crap, int morecrap) +{ + switch (special) { + case GLUT_KEY_LEFT: + view_rot[1] += 5.0; + break; + case GLUT_KEY_RIGHT: + view_rot[1] -= 5.0; + break; + case GLUT_KEY_UP: + view_rot[0] += 5.0; + break; + case GLUT_KEY_DOWN: + view_rot[0] -= 5.0; + break; + } +} + +static void +gears_idle(void) +{ + static int frames = 0; + static double tRot0 = -1.0, tRate0 = -1.0; + double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; + + if (tRot0 < 0.0) + tRot0 = t; + dt = t - tRot0; + tRot0 = t; + + /* advance rotation for next frame */ + angle += 70.0 * dt; /* 70 degrees per second */ + if (angle > 3600.0) + angle -= 3600.0; + + glutPostRedisplay(); + frames++; + + if (tRate0 < 0.0) + tRate0 = t; + if (t - tRate0 >= 5.0) { + GLfloat seconds = t - tRate0; + GLfloat fps = frames / seconds; + printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, + fps); + tRate0 = t; + frames = 0; + } +} + +static const char vertex_shader[] = +"attribute vec3 position;\n" +"attribute vec3 normal;\n" +"\n" +"uniform mat4 ModelViewProjectionMatrix;\n" +"uniform mat4 NormalMatrix;\n" +"uniform vec4 LightSourcePosition;\n" +"uniform vec4 MaterialColor;\n" +"\n" +"varying vec4 Color;\n" +"\n" +"void main(void)\n" +"{\n" +" // Transform the normal to eye coordinates\n" +" vec3 N = normalize(vec3(NormalMatrix * vec4(normal, 1.0)));\n" +"\n" +" // The LightSourcePosition is actually its direction for directional light\n" +" vec3 L = normalize(LightSourcePosition.xyz);\n" +"\n" +" // Multiply the diffuse value by the vertex color (which is fixed in this case)\n" +" // to get the actual color that we will use to draw this vertex with\n" +" float diffuse = max(dot(N, L), 0.0);\n" +" Color = diffuse * MaterialColor;\n" +"\n" +" // Transform the position to clip coordinates\n" +" gl_Position = ModelViewProjectionMatrix * vec4(position, 1.0);\n" +"}"; + +static const char fragment_shader[] = +"#ifdef GL_ES\n" +"precision mediump float;\n" +"#endif\n" +"varying vec4 Color;\n" +"\n" +"void main(void)\n" +"{\n" +" vec2 d = dFdx(Color.xy);\n" +" gl_FragColor = Color;\n" +"}"; + +static void +gears_init(void) +{ + GLuint v, f, program; + const char *p; + char msg[512]; + + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + + /* Compile the vertex shader */ + p = vertex_shader; + v = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(v, 1, &p, NULL); + glCompileShader(v); + glGetShaderInfoLog(v, sizeof msg, NULL, msg); + printf("vertex shader info: %s\n", msg); + + /* Compile the fragment shader */ + p = fragment_shader; + f = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(f, 1, &p, NULL); + glCompileShader(f); + glGetShaderInfoLog(f, sizeof msg, NULL, msg); + printf("fragment shader info: %s\n", msg); + + /* Create and link the shader program */ + program = glCreateProgram(); + glAttachShader(program, v); + glAttachShader(program, f); + glBindAttribLocation(program, 0, "position"); + glBindAttribLocation(program, 1, "normal"); + + glLinkProgram(program); + glGetProgramInfoLog(program, sizeof msg, NULL, msg); + printf("info: %s\n", msg); + + /* Enable the shaders */ + glUseProgram(program); + + /* Get the locations of the uniforms so we can access them */ + ModelViewProjectionMatrix_location = glGetUniformLocation(program, "ModelViewProjectionMatrix"); + NormalMatrix_location = glGetUniformLocation(program, "NormalMatrix"); + LightSourcePosition_location = glGetUniformLocation(program, "LightSourcePosition"); + MaterialColor_location = glGetUniformLocation(program, "MaterialColor"); + + /* Set the LightSourcePosition uniform which is constant throught the program */ + glUniform4fv(LightSourcePosition_location, 1, LightSourcePosition); + + /* make the gears */ + gear1 = create_gear(1.0, 4.0, 1.0, 20, 0.7); + gear2 = create_gear(0.5, 2.0, 2.0, 10, 0.7); + gear3 = create_gear(1.3, 2.0, 0.5, 10, 0.7); +} + +int +main(int argc, char *argv[]) +{ + /* Initialize the window */ + glutInit(&argc, argv); + glutInitWindowSize(300, 300); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); + + glutCreateWindow("es2gears"); + + /* Set up glut callback functions */ + gears_idle(); + glutReshapeFunc(gears_reshape); + glutDisplayFunc(gears_draw); + glutSpecialFunc(gears_special); + + /* Initialize the gears */ + gears_init(); + + glutMainLoop(); + + return 0; +} diff --git a/tests/runner.py b/tests/runner.py index 58a94c17..9ea8cd9f 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -5230,7 +5230,7 @@ def process(filename): 'postRun': function() { Module.print('*'); var ret; - ret = ccall('get_int', 'number'); Module.print([typeof ret, ret]); + ret = Module['ccall']('get_int', 'number'); Module.print([typeof ret, ret]); ret = ccall('get_float', 'number'); Module.print([typeof ret, ret.toFixed(2)]); ret = ccall('get_string', 'string'); Module.print([typeof ret, ret]); ret = ccall('print_int', null, ['number'], [12]); Module.print(typeof ret); @@ -5242,7 +5242,7 @@ def process(filename): ret = ccall('pointer', 'pointer', ['pointer'], [p]); Module.print([typeof ret, getValue(ret, 'i32')]); Module.print('*'); // part 2: cwrap - var multi = cwrap('multi', 'number', ['number', 'number', 'number', 'string']); + var multi = Module['cwrap']('multi', 'number', ['number', 'number', 'number', 'string']); Module.print(multi(2, 1.4, 3, 'atr')); Module.print(multi(8, 5.4, 4, 'bret')); Module.print('*'); @@ -6337,6 +6337,35 @@ f.close() Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-L' + os.path.join(self.get_dir(), 'libdir'), '-lfile'], stdout=PIPE, stderr=STDOUT).communicate() self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + def test_local_link(self): + # Linking a local library directly, like /usr/lib/libsomething.so, cannot work of course since it + # doesn't contain bitcode. However, when we see that we should look for a bitcode file for that + # library in the -L paths and system/lib + open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(''' + extern void printey(); + int main() { + printey(); + return 0; + } + ''') + + try: + os.makedirs(os.path.join(self.get_dir(), 'subdir')); + except: + pass + open(os.path.join(self.get_dir(), 'subdir', 'libfile.so'), 'w').write('this is not llvm bitcode!') + + open(os.path.join(self.get_dir(), 'libfile.cpp'), 'w').write(''' + #include <stdio.h> + void printey() { + printf("hello from lib\\n"); + } + ''') + + Popen(['python', EMCC, os.path.join(self.get_dir(), 'libfile.cpp'), '-o', 'libfile.so']).communicate() + Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp'), os.path.join(self.get_dir(), 'subdir', 'libfile.so'), '-L.']).communicate() + self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + def test_embed_file(self): open(os.path.join(self.get_dir(), 'somefile.txt'), 'w').write('''hello from a file with lots of data and stuff in it thank you very much''') open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r''' @@ -6572,8 +6601,8 @@ elif 'browser' in str(sys.argv): doReftest.done = true; var img = new Image(); img.onload = function() { - assert(img.width == Module.canvas.width); - assert(img.height == Module.canvas.height); + assert(img.width == Module.canvas.width, 'Invalid width: ' + Module.canvas.width + ', should be ' + img.width); + assert(img.height == Module.canvas.height, 'Invalid height: ' + Module.canvas.height + ', should be ' + img.height); var canvas = document.createElement('canvas'); canvas.width = img.width; @@ -6610,8 +6639,10 @@ elif 'browser' in str(sys.argv): } img.src = '%s'; }; - Module.postRun = doReftest(); - setTimeout(doReftest, 0); // if run() throws an exception, this will kick in + Module['postRun'] = doReftest; + Module['preRun'] = function() { + setTimeout(doReftest, 0); // if run() throws an exception and postRun is not called, this will kick in + }; ''' % basename) def test_compression(self): @@ -6880,17 +6911,39 @@ elif 'browser' in str(sys.argv): assert os.path.exists('something.html'), output self.run_browser('something.html', 'You should not see animating gears.', '/report_gl_result?false') + def test_glgears_deriv(self): + self.reftest(path_from_root('tests', 'gears.png')) + output = Popen(['python', EMCC, path_from_root('tests', 'hello_world_gles_deriv.c'), '-o', 'something.html', + '-DHAVE_BUILTIN_SINCOS', '--pre-js', 'reftest.js'], + stdout=PIPE, stderr=PIPE).communicate() + assert len(output[0]) == 0, output[0] + assert os.path.exists('something.html'), output + self.run_browser('something.html', 'You should see animating gears.', '/report_result?0') + def test_glbook(self): programs = self.get_library('glbook', [ os.path.join('Chapter_2', 'Hello_Triangle', 'CH02_HelloTriangle.bc'), os.path.join('Chapter_8', 'Simple_VertexShader', 'CH08_SimpleVertexShader.bc'), os.path.join('Chapter_9', 'Simple_Texture2D', 'CH09_SimpleTexture2D.bc'), os.path.join('Chapter_9', 'Simple_TextureCubemap', 'CH09_TextureCubemap.bc'), + os.path.join('Chapter_9', 'TextureWrap', 'CH09_TextureWrap.bc'), + os.path.join('Chapter_10', 'MultiTexture', 'CH10_MultiTexture.bc'), + os.path.join('Chapter_13', 'ParticleSystem', 'CH13_ParticleSystem.bc'), ], configure=None) for program in programs: print program - self.reftest(path_from_root('tests', 'glbook', os.path.basename(program).replace('.bc', '.png'))) - Popen(['python', EMCC, program, '-o', 'program.html', '--pre-js', 'reftest.js']).communicate() + basename = os.path.basename(program) + args = [] + if basename == 'CH10_MultiTexture.bc': + shutil.copyfile(path_from_root('tests', 'glbook', 'Chapter_10', 'MultiTexture', 'basemap.tga'), os.path.join(self.get_dir(), 'basemap.tga')) + shutil.copyfile(path_from_root('tests', 'glbook', 'Chapter_10', 'MultiTexture', 'lightmap.tga'), os.path.join(self.get_dir(), 'lightmap.tga')) + args = ['--preload-file', 'basemap.tga', '--preload-file', 'lightmap.tga'] + elif basename == 'CH13_ParticleSystem.bc': + shutil.copyfile(path_from_root('tests', 'glbook', 'Chapter_13', 'ParticleSystem', 'smoke.tga'), os.path.join(self.get_dir(), 'smoke.tga')) + args = ['--preload-file', 'smoke.tga', '-O2'] # test optimizations and closure here as well for more coverage + + self.reftest(path_from_root('tests', 'glbook', basename.replace('.bc', '.png'))) + Popen(['python', EMCC, program, '-o', 'program.html', '--pre-js', 'reftest.js'] + args).communicate() self.run_browser('program.html', '', '/report_result?0') elif 'benchmark' in str(sys.argv): diff --git a/tools/clean_webconsole.py b/tools/clean_webconsole.py index 550ace9a..56bd9e2b 100644 --- a/tools/clean_webconsole.py +++ b/tools/clean_webconsole.py @@ -9,7 +9,9 @@ lines = sys.stdin.read().split('\n') for line in lines: if line.startswith('['): line = line[15:] - if line.startswith(('[', ']')): - line = line.split('@')[0] + line = line.split(' @ ')[0] print line +for i in range(100): + print + diff --git a/tools/shared.py b/tools/shared.py index 6fa4444e..e11dc95a 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -184,7 +184,7 @@ else: if 'gcparam' not in str(SPIDERMONKEY_ENGINE): SPIDERMONKEY_ENGINE += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap -WINDOWS = 'win' in sys.platform +WINDOWS = sys.platform.startswith ('win') # Temp file utilities |