diff options
-rwxr-xr-x | emscripten.py | 4 | ||||
-rw-r--r-- | src/jsifier.js | 21 | ||||
-rw-r--r-- | src/library_gl.js | 29 | ||||
-rw-r--r-- | src/parseTools.js | 3 | ||||
-rw-r--r-- | src/settings.js | 14 | ||||
-rw-r--r-- | system/include/libc/math.h | 3 | ||||
-rw-r--r-- | system/include/libc/sys/resource.h | 8 | ||||
-rw-r--r-- | tests/cases/abs.ll | 22 | ||||
-rw-r--r-- | tests/cases/caall.ll | 25 | ||||
-rw-r--r-- | tests/gl_renderers.c | 191 | ||||
-rw-r--r-- | tests/gl_renderers.png | bin | 0 -> 345620 bytes | |||
-rwxr-xr-x | tests/runner.py | 16 | ||||
-rw-r--r-- | tools/shared.py | 9 |
13 files changed, 298 insertions, 47 deletions
diff --git a/emscripten.py b/emscripten.py index 1b62d977..d41aaa2c 100755 --- a/emscripten.py +++ b/emscripten.py @@ -146,7 +146,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, out = jcache.get(shortkey, keys) if DEBUG_CACHE and not out: - dfpath = os.path.join(configuration.TEMP_DIR, "ems_" + shortkey) + dfpath = os.path.join(get_configuration().TEMP_DIR, "ems_" + shortkey) dfp = open(dfpath, 'w') dfp.write(pre_input); dfp.write("\n\n========================== settings_text\n\n"); @@ -282,7 +282,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, if len(parts) > 1: pre = parts[0] outputs.append([parts[1]]) - funcs_js = [''.join([output[0] for output in outputs])] # this will be a list of things, so we do not do string appending as we add more + funcs_js = [output[0] for output in outputs] outputs = None if DEBUG: print >> sys.stderr, ' emscript: phase 2b took %s seconds' % (time.time() - t) diff --git a/src/jsifier.js b/src/jsifier.js index c55072b4..69d9842a 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -441,7 +441,7 @@ function JSify(data, functionsOnly, givenFunctions) { } // In asm, we need to know about library functions. If there is a target, though, then no // need to consider this a library function - we will call directly to it anyhow - if (ASM_JS && !redirectedIdent && (typeof target == 'function' || /Math\..+/.exec(snippet))) { + if (ASM_JS && !redirectedIdent && (typeof target == 'function' || /Math\.\w+/.exec(snippet))) { Functions.libraryFunctions[ident] = 1; } } else if (typeof snippet === 'object') { @@ -1322,9 +1322,10 @@ function JSify(data, functionsOnly, givenFunctions) { ident = Variables.resolveAliasToIdent(ident); var shortident = ident.slice(1); - var callIdent = LibraryManager.getRootIdent(shortident); + var simpleIdent = shortident; + var callIdent = LibraryManager.getRootIdent(simpleIdent); if (callIdent) { - shortident = callIdent; // ident may not be in library, if all there is is ident__inline, but in this case it is + simpleIdent = callIdent; // ident may not be in library, if all there is is ident__inline, but in this case it is if (callIdent.indexOf('.') < 0) { callIdent = '_' + callIdent; // Not Math.*, so add the normal prefix } @@ -1339,7 +1340,7 @@ function JSify(data, functionsOnly, givenFunctions) { var varargsTypes = []; var varargsByVals = {}; var ignoreFunctionIndexizing = []; - var useJSArgs = (shortident + '__jsargs') in LibraryManager.library; + var useJSArgs = (simpleIdent + '__jsargs') in LibraryManager.library; var hasVarArgs = isVarArgsFunctionType(type); var normalArgs = (hasVarArgs && !useJSArgs) ? countNormalArgs(type) : -1; var byPointer = getVarData(funcData, ident); @@ -1367,7 +1368,7 @@ function JSify(data, functionsOnly, givenFunctions) { args = args.map(function(arg, i) { return indexizeFunctions(arg, argsTypes[i]) }); if (ASM_JS) { - if (shortident in Functions.libraryFunctions) { + if (shortident in Functions.libraryFunctions || simpleIdent in Functions.libraryFunctions) { args = args.map(function(arg, i) { return asmCoercion(arg, argsTypes[i]) }); } else { args = args.map(function(arg, i) { return asmEnsureFloat(arg, argsTypes[i]) }); @@ -1411,8 +1412,8 @@ function JSify(data, functionsOnly, givenFunctions) { var argsText = args.join(', '); // Inline if either we inline whenever we can (and we can), or if there is no noninlined version - var inline = LibraryManager.library[shortident + '__inline']; - var nonInlined = shortident in LibraryManager.library; + var inline = LibraryManager.library[simpleIdent + '__inline']; + var nonInlined = simpleIdent in LibraryManager.library; if (inline && (INLINE_LIBRARY_FUNCS || !nonInlined)) { return inline.apply(null, args); // Warning: inlining does not prevent recalculation of the arguments. They should be simple identifiers } @@ -1420,7 +1421,7 @@ function JSify(data, functionsOnly, givenFunctions) { if (ASM_JS) { // remove unneeded arguments, which the asm sig can show us. this lets us alias memset with llvm.memset, we just // drop the final 2 args so things validate properly in asm - var libsig = LibraryManager.library[shortident + '__sig']; + var libsig = LibraryManager.library[simpleIdent + '__sig']; if (libsig) { assert(!hasVarArgs); while (libsig.length - 1 < args.length) { @@ -1454,9 +1455,9 @@ function JSify(data, functionsOnly, givenFunctions) { } var ret = callIdent + '(' + args.join(', ') + ')'; - if (ASM_JS) { // TODO: do only when needed (library functions and Math.*?) XXX && shortident in Functions.libraryFunctions) { + if (ASM_JS) { // TODO: do only when needed (library functions and Math.*?) XXX && simpleIdent in Functions.libraryFunctions) { ret = asmCoercion(ret, returnType); - if (shortident == 'abort' && funcData.returnType != 'void') { + if (simpleIdent == 'abort' && funcData.returnType != 'void') { ret += '; return 0'; // special case: abort() can happen without return, breaking the return type of asm functions. ensure a return } } diff --git a/src/library_gl.js b/src/library_gl.js index 297a36cf..0912b5da 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -1222,6 +1222,9 @@ var LibraryGL = { // Add some emulation workarounds Module.printErr('WARNING: using emscripten GL emulation. This is a collection of limited workarounds, do not expect it to work'); +#if GL_UNSAFE_OPTS == 0 + Module.printErr('WARNING: using emscripten GL emulation unsafe opts. If weirdness happens, try -s GL_UNSAFE_OPTS=0'); +#endif // XXX some of the capabilities we don't support may lead to incorrect rendering, if we do not emulate them in shaders var validCapabilities = { @@ -1798,6 +1801,7 @@ var LibraryGL = { lastRenderer: null, // used to avoid cleaning up and re-preparing the same renderer lastArrayBuffer: null, // used in conjunction with lastRenderer lastProgram: null, // "" + lastStride: -1, // "" // The following data structures are used for OpenGL Immediate Mode matrix routines. matrix: {}, @@ -1874,8 +1878,6 @@ var LibraryGL = { var typeIndex = attribute.type - GL.byteSizeByTypeRoot; // ensure it starts at 0 to keep the cache items dense temp = cacheItem[typeIndex]; cacheItem = temp ? temp : (cacheItem[typeIndex] = GL.immediate.rendererCacheItemTemplate.slice()); - temp = cacheItem[attribute.stride]; - cacheItem = temp ? temp : (cacheItem[attribute.stride] = GL.immediate.rendererCacheItemTemplate.slice()); } var fogParam; if (GLEmulation.fogEnabled) { @@ -1910,30 +1912,25 @@ var LibraryGL = { createRenderer: function(renderer) { var useCurrProgram = !!GL.currProgram; - var hasTextures = false, textureSizes = [], textureTypes = [], textureOffsets = []; + var hasTextures = false, textureSizes = [], textureTypes = []; for (var i = 0; i < GL.immediate.NUM_TEXTURES; i++) { if (GL.immediate.enabledClientAttributes[GL.immediate.TEXTURE0 + i]) { textureSizes[i] = GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].size; textureTypes[i] = GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].type; - textureOffsets[i] = GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].offset; hasTextures = true; } } - var stride = GL.immediate.stride; var positionSize = GL.immediate.clientAttributes[GL.immediate.VERTEX].size; var positionType = GL.immediate.clientAttributes[GL.immediate.VERTEX].type; - var positionOffset = GL.immediate.clientAttributes[GL.immediate.VERTEX].offset; - var colorSize = 0, colorType, colorOffset; + var colorSize = 0, colorType; if (GL.immediate.enabledClientAttributes[GL.immediate.COLOR]) { colorSize = GL.immediate.clientAttributes[GL.immediate.COLOR].size; colorType = GL.immediate.clientAttributes[GL.immediate.COLOR].type; - colorOffset = GL.immediate.clientAttributes[GL.immediate.COLOR].offset; } - var normalSize = 0, normalType, normalOffset; + var normalSize = 0, normalType; if (GL.immediate.enabledClientAttributes[GL.immediate.NORMAL]) { normalSize = GL.immediate.clientAttributes[GL.immediate.NORMAL].size; normalType = GL.immediate.clientAttributes[GL.immediate.NORMAL].type; - normalOffset = GL.immediate.clientAttributes[GL.immediate.NORMAL].offset; } var ret = { init: function() { @@ -2075,6 +2072,7 @@ var LibraryGL = { var canSkip = this == lastRenderer && arrayBuffer == GL.immediate.lastArrayBuffer && (GL.currProgram || this.program) == GL.immediate.lastProgram && + GL.immediate.stride == GL.immediate.lastStride && !GL.immediate.matricesModified; if (!canSkip && lastRenderer) lastRenderer.cleanup(); #endif @@ -2095,6 +2093,7 @@ var LibraryGL = { GL.immediate.lastRenderer = this; GL.immediate.lastArrayBuffer = arrayBuffer; GL.immediate.lastProgram = GL.currProgram || this.program; + GL.immediate.lastStride == GL.immediate.stride; GL.immediate.matricesModified = false; #endif @@ -2106,13 +2105,13 @@ var LibraryGL = { if (this.projectionLocation) Module.ctx.uniformMatrix4fv(this.projectionLocation, false, GL.immediate.matrix['p']); Module.ctx.vertexAttribPointer(this.positionLocation, positionSize, positionType, false, - stride, positionOffset); + GL.immediate.stride, GL.immediate.clientAttributes[GL.immediate.VERTEX].offset); Module.ctx.enableVertexAttribArray(this.positionLocation); if (this.hasTextures) { for (var i = 0; i < textureSizes.length; i++) { if (textureSizes[i] && this.texCoordLocations[i] >= 0) { Module.ctx.vertexAttribPointer(this.texCoordLocations[i], textureSizes[i], textureTypes[i], false, - stride, textureOffsets[i]); + GL.immediate.stride, GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + i].offset); Module.ctx.enableVertexAttribArray(this.texCoordLocations[i]); } } @@ -2124,7 +2123,7 @@ var LibraryGL = { } if (this.hasColorAttrib) { Module.ctx.vertexAttribPointer(this.colorLocation, colorSize, colorType, true, - stride, colorOffset); + GL.immediate.stride, GL.immediate.clientAttributes[GL.immediate.COLOR].offset); Module.ctx.enableVertexAttribArray(this.colorLocation); Module.ctx.uniform1i(this.hasColorAttribLocation, 1); } else if (this.hasColorUniform) { @@ -2133,7 +2132,7 @@ var LibraryGL = { } if (this.hasNormal) { Module.ctx.vertexAttribPointer(this.normalLocation, normalSize, normalType, true, - stride, normalOffset); + GL.immediate.stride, GL.immediate.clientAttributes[GL.immediate.NORMAL].offset); Module.ctx.enableVertexAttribArray(this.normalLocation); } if (!useCurrProgram) { // otherwise, the user program will set the sampler2D binding and uniform itself @@ -2282,7 +2281,7 @@ var LibraryGL = { if (GL.immediate.enabledClientAttributes[i]) attributes.push(GL.immediate.clientAttributes[i]); } attributes.sort(function(x, y) { return !x ? (!y ? 0 : 1) : (!y ? -1 : (x.pointer - y.pointer)) }); - start = attributes[0].pointer; + start = GL.currArrayBuffer ? 0 : attributes[0].pointer; for (var i = 0; i < attributes.length; i++) { var attribute = attributes[i]; if (!attribute) break; diff --git a/src/parseTools.js b/src/parseTools.js index d0d3e89f..6818e442 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -65,7 +65,7 @@ function pointingLevels(type) { var ret = 0; var len1 = type.length - 1; while (type[len1-ret] && type[len1-ret] === '*') { - ret ++; + ret++; } return ret; } @@ -234,6 +234,7 @@ function isFunctionType(type, out) { } function getReturnType(type) { + if (pointingLevels(type) > 1) return '*'; // the type of a call can be either the return value, or the entire function. ** or more means it is a return value var lastOpen = type.lastIndexOf('('); if (lastOpen > 0) { return type.substr(0, lastOpen-1); diff --git a/src/settings.js b/src/settings.js index 9ed87bd6..6b054443 100644 --- a/src/settings.js +++ b/src/settings.js @@ -335,10 +335,16 @@ var PGO = 0; // Enables profile-guided optimization in the form of runtime check // which functions are actually called. Emits a list during shutdown that you // can pass to DEAD_FUNCTIONS (you can also emit the list manually by // calling PGOMonitor.dump()); -var DEAD_FUNCTIONS = []; // A list of functions that no code will be emitted for, and - // a runtime abort will happen if they are called. If - // such a function is an unresolved reference, that is not - // considered an error. +var DEAD_FUNCTIONS = []; // Functions on this list are not converted to JS, and calls to + // them are turned into abort()s. This is potentially useful for + // (1) reducing code size, if you know some function will never + // be called (see PGO), and also (2) ASM.js requires all declared + // functions to have a corresponding implementation (even if the + // function is never called) and will emit an error during linking if no + // implementation can be found; with this option, asm.js validation will + // succeed for that function and calls to it. + // If a dead function is actually called, you will get a runtime + // error. // TODO: options to lazily load such functions var UNRESOLVED_AS_DEAD = 0; // Handle all unresolved functions as if they were in the // list of dead functions. This is a quick way to turn diff --git a/system/include/libc/math.h b/system/include/libc/math.h index e2f8cdef..3bd0621c 100644 --- a/system/include/libc/math.h +++ b/system/include/libc/math.h @@ -145,9 +145,10 @@ extern double fmod _PARAMS((double, double)); #ifndef FLT_EVAL_METHOD #define FLT_EVAL_METHOD 0 +#endif /* FLT_EVAL_METHOD */ +/* XXX EMSCRIPTEN: moved these out of previous if */ typedef float float_t; typedef double double_t; -#endif /* FLT_EVAL_METHOD */ #define FP_NAN 0 #define FP_INFINITE 1 diff --git a/system/include/libc/sys/resource.h b/system/include/libc/sys/resource.h index abcfd34d..1e451e0d 100644 --- a/system/include/libc/sys/resource.h +++ b/system/include/libc/sys/resource.h @@ -3,6 +3,10 @@ #include <sys/time.h> +#ifdef __cplusplus +extern "C" { +#endif + #define RUSAGE_SELF 0 /* calling process */ #define RUSAGE_CHILDREN -1 /* terminated child processes */ @@ -47,5 +51,9 @@ struct rlimit { int getrlimit(int resource, struct rlimit *rlim); int setrlimit(int resource, const struct rlimit *rlim); +#ifdef __cplusplus +} +#endif + #endif diff --git a/tests/cases/abs.ll b/tests/cases/abs.ll new file mode 100644 index 00000000..57e06928 --- /dev/null +++ b/tests/cases/abs.ll @@ -0,0 +1,22 @@ +; ModuleID = 'tests/hello_world.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +target triple = "i386-pc-linux-gnu" + +@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] + +; [#uses=0] +define i32 @main() { +entry: + %retval = alloca i32, align 4 ; [#uses=1 type=i32*] + store i32 0, i32* %retval + %zero = zext i8 0 to i32 + %a = call i32 (i32)* @abs(i32 %zero) + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), i32 %a, i32 %zero) ; [#uses=0 type=i32] + ret i32 1 +} + +; [#uses=1] +declare i32 @printf(i8*, ...) + +declare i32 @abs(i32) + diff --git a/tests/cases/caall.ll b/tests/cases/caall.ll new file mode 100644 index 00000000..313116e6 --- /dev/null +++ b/tests/cases/caall.ll @@ -0,0 +1,25 @@ +; ModuleID = 'tests/hello_world.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +target triple = "i386-pc-linux-gnu" + +@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] + +; [#uses=0] +define i32 @main() { +entry: + %retval = alloca i32, align 4 ; [#uses=1 type=i32*] + store i32 0, i32* %retval + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] + %call12 = call void (i32*)** @_ZNSt3__13mapINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPFvP6ObjectENS_4lessIS6_EENS4_INS_4pairIKS6_SA_EEEEEixERSE_(i32 10) + %26 = load void (%class.Object*)** %call12 + ret i32 1 +} + +define (i32*)** @_ZNSt3__13mapINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPFvP6ObjectENS_4lessIS6_EENS4_INS_4pairIKS6_SA_EEEEEixERSE_(i32 %x) { +entry: + %ret = inttoptr i32 0 to (i32*)** + ret %ret +} + +; [#uses=1] +declare i32 @printf(i8*, ...) diff --git a/tests/gl_renderers.c b/tests/gl_renderers.c new file mode 100644 index 00000000..0a8e6e78 --- /dev/null +++ b/tests/gl_renderers.c @@ -0,0 +1,191 @@ +/******************************************************************* + * * + * Using SDL With OpenGL * + * * + * Tutorial by Kyle Foley (sdw) * + * * + * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL * + * * + *******************************************************************/ + +/* +THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION +AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN. + +THE ORIGINAL AUTHOR IS KYLE FOLEY. + +THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY +OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF +MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, +ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE +RESULTING FROM THE USE, MODIFICATION, OR +REDISTRIBUTION OF THIS SOFTWARE. +*/ + +#if !EMSCRIPTEN +#define USE_GLEW 0 +#endif + +#if USE_GLEW +#include "GL/glew.h" +#endif + +#include "SDL/SDL.h" +#include "SDL/SDL_image.h" +#if !USE_GLEW +#include "SDL/SDL_opengl.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + + // Slightly different SDL initialization + if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) { + printf("Unable to initialize SDL: %s\n", SDL_GetError()); + return 1; + } + + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new* + + screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed* + if ( !screen ) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + // Set the OpenGL state after creating the context with SDL_SetVideoMode + + glClearColor( 0, 0, 0, 0 ); + +#if !EMSCRIPTEN + glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL +#endif + + glViewport( 0, 0, 640, 480 ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + + // Clear the screen before drawing + glClear( GL_COLOR_BUFFER_BIT ); + + typedef struct Vertex { + GLfloat x; + GLfloat y; + } Vertex; + + typedef struct Color { + GLubyte r; + GLubyte g; + GLubyte b; + GLubyte a; + } Color; + + typedef struct Type1 { + Vertex location; + Color color; + } Type1; + + typedef struct Type2 { + GLuint unused1; + Vertex location; + GLfloat unused2; + Color color; + } Type2; + + Type1 first[3] = { + {{-1.0, 0.0}, {0xFF, 0x00, 0x00, 0xFF}}, + {{ 0.0, 1.0}, {0x00, 0xFF, 0x00, 0xFF}}, + {{ 1.0, 0.0}, {0x00, 0x00, 0xFF, 0xFF}} + }; + + Type2 second[3] = { + {0.0, {-1.0, 0.0}, 0.0, {0xFF, 0x00, 0x00, 0xFF}}, + {0.0, { 1.0, 0.0}, 0.0, {0x00, 0x00, 0xFF, 0xFF}}, + {0.0, { 0.0, -1.0}, 0.0, {0x00, 0xFF, 0x00, 0xFF}}}; + + // make two vbo objects + GLuint vbo[2]; + glGenBuffers(2, &vbo[0]); + + // load the first into the context + glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); + + // allocate enough space for 100 vertices + glBufferData(GL_ARRAY_BUFFER, sizeof(Type1)*100, NULL, GL_DYNAMIC_DRAW); + + // load the second into the context + glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); + + // allocate enough space for 100 vertices + glBufferData(GL_ARRAY_BUFFER, sizeof(Type2)*100, NULL, GL_DYNAMIC_DRAW); + + // DRAW + + GLbyte * pointer; + + // Clear the screen before drawing + glClear( GL_COLOR_BUFFER_BIT ); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + // FIRST + // load the first into the context + glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); + + // Load actual data in + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Type1)*3, &first[0]); + + // point to the buffer's location data + glVertexPointer(2, GL_FLOAT, sizeof(Type1), NULL); + + pointer = (GLbyte*)(((GLbyte*)&first[0].color) - ((GLbyte*)&first[0].location)); + + printf("location = %p\n", pointer); + // point to the buffer's color data + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Type1), pointer); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + + // SECOND + + // load the first into the context + glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); + + // Load actual data in + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Type2)*3, &second[0]); + + pointer = (GLbyte*)((GLbyte*)&second[0].location - (GLbyte*)&second[0].unused1); + + // point to the buffer's location data + printf("location = %p\n", pointer); + glVertexPointer(2, GL_FLOAT, sizeof(Type2), pointer); + + pointer = (GLbyte*)((GLbyte*)&second[0].color - (GLbyte*)&second[0].unused1); + + // point to the buffer's location data + printf("location = %p\n", pointer); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Type2), pointer); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + SDL_GL_SwapBuffers(); + +#if !EMSCRIPTEN + // Wait for 3 seconds to give us a chance to see the image + SDL_Delay(3000); +#endif + + SDL_Quit(); + + return 0; +} diff --git a/tests/gl_renderers.png b/tests/gl_renderers.png Binary files differnew file mode 100644 index 00000000..db1bc751 --- /dev/null +++ b/tests/gl_renderers.png diff --git a/tests/runner.py b/tests/runner.py index a3c74f03..ef014a18 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -1635,7 +1635,11 @@ Succeeded! def test_floatvars(self): src = ''' #include <stdio.h> - #include <math.h> + + // headers test, see issue #1013 + #include<cfloat> + #include<cmath> + int main(int argc, char **argv) { float x = 1.234, y = 3.5, q = 0.00000001; @@ -2479,7 +2483,6 @@ Exception execution path of first function! 1 Settings.EXCEPTION_DEBUG = 1 - self.banned_js_engines = [NODE_JS] # node issue 1669, exception causes stdout not to be flushed Settings.DISABLE_EXCEPTION_CATCHING = 0 if '-O2' in self.emcc_args: self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage @@ -7220,7 +7223,6 @@ void*:16 def test_mmap(self): if self.emcc_args is None: return self.skip('requires emcc') - self.banned_js_engines = [NODE_JS] # slower, and fail on 64-bit Settings.TOTAL_MEMORY = 128*1024*1024 @@ -7669,7 +7671,6 @@ def process(filename): try: os.environ['EMCC_LEAVE_INPUTS_RAW'] = '1' - #self.banned_js_engines = [NODE_JS] # node issue 1669, exception causes stdout not to be flushed Settings.CHECK_OVERFLOWS = 0 for name in glob.glob(path_from_root('tests', 'cases', '*.ll')): @@ -10098,8 +10099,8 @@ f.close() try: os.environ['EMCC_DEBUG'] = '1' for asm, linkable, chunks, js_chunks in [ - (0, 0, 3, 2), (0, 1, 3, 4), - (1, 0, 3, 2), (1, 1, 3, 4) + (0, 0, 3, 2), (0, 1, 4, 4), + (1, 0, 3, 2), (1, 1, 4, 4) ]: print asm, linkable, chunks, js_chunks output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm, '-s', 'UNRESOLVED_AS_DEAD=1'] + (['-O2'] if asm else []), stdout=PIPE, stderr=PIPE).communicate() @@ -11530,6 +11531,9 @@ elif 'browser' in str(sys.argv): shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.btest('gl_ps_strides.c', reference='gl_ps_strides.png', args=['--preload-file', 'screenshot.png']) + def test_gl_renderers(self): + self.btest('gl_renderers.c', reference='gl_renderers.png', args=['-s', 'GL_UNSAFE_OPTS=0']) + def test_matrix_identity(self): self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840']) diff --git a/tools/shared.py b/tools/shared.py index 19206b6d..c492ba49 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -274,7 +274,6 @@ LLVM_DIS=os.path.expanduser(build_llvm_tool_path('llvm-dis')) LLVM_NM=os.path.expanduser(build_llvm_tool_path('llvm-nm')) LLVM_INTERPRETER=os.path.expanduser(build_llvm_tool_path('lli')) LLVM_COMPILER=os.path.expanduser(build_llvm_tool_path('llc')) -LLVM_EXTRACT=os.path.expanduser(build_llvm_tool_path('llvm-extract')) EMSCRIPTEN = path_from_root('emscripten.py') DEMANGLER = path_from_root('third_party', 'demangler.py') @@ -385,8 +384,7 @@ USE_EMSDK = not os.environ.get('EMMAKEN_NO_SDK') if USE_EMSDK: # Disable system C and C++ include directories, and add our own (using -idirafter so they are last, like system dirs, which # allows projects to override them) - # Note that -nostdinc++ is not needed, since -nostdinc implies that! - EMSDK_OPTS = ['-nostdinc', '-Xclang', '-nobuiltininc', '-Xclang', '-nostdsysteminc', + EMSDK_OPTS = ['-nostdinc', '-nostdinc++', '-Xclang', '-nobuiltininc', '-Xclang', '-nostdsysteminc', '-Xclang', '-isystem' + path_from_root('system', 'local', 'include'), '-Xclang', '-isystem' + path_from_root('system', 'include', 'libcxx'), '-Xclang', '-isystem' + path_from_root('system', 'include'), @@ -721,11 +719,6 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e return generated_libs @staticmethod - def remove_symbol(filename, symbol): - Popen([LLVM_EXTRACT, filename, '-delete', '-glob=' + symbol, '-o', filename], stderr=PIPE).communicate() - Popen([LLVM_EXTRACT, filename, '-delete', '-func=' + symbol, '-o', filename], stderr=PIPE).communicate() - - @staticmethod def link(files, target): actual_files = [] unresolved_symbols = set(['main']) # tracking unresolveds is necessary for .a linking, see below. (and main is always a necessary symbol) |