diff options
44 files changed, 2709 insertions, 1105 deletions
@@ -77,4 +77,5 @@ a license to everyone to use it as detailed in LICENSE.) * Martin Gerhardy <martin.gerhardy@gmail.com> * James Gregory <jgregory@zynga.com> (copyright owned by Zynga, Inc) * Dan Gohman <sunfish@google.com> (copyright owned by Google, Inc.) +* Jeff Gilbert <jgilbert@mozilla.com> (copyright owned by Mozilla Foundation) diff --git a/src/jsifier.js b/src/jsifier.js index 77aff895..156fd65d 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -460,6 +460,7 @@ function JSify(data, functionsOnly, givenFunctions) { } else { ident = '_' + ident; } + if (VERBOSE) printErr('adding ' + ident + ' and deps ' + deps); var depsText = (deps ? '\n' + deps.map(addFromLibrary).filter(function(x) { return x != '' }).join('\n') : ''); var contentText = isFunction ? snippet : ('var ' + ident + '=' + snippet + ';'); if (ASM_JS) { diff --git a/src/library.js b/src/library.js index e65754ba..51c4c5cb 100644 --- a/src/library.js +++ b/src/library.js @@ -560,6 +560,7 @@ LibraryManager.library = { var stdout = FS.createDevice(devFolder, 'stdout', null, output); var stderr = FS.createDevice(devFolder, 'stderr', null, error); FS.createDevice(devFolder, 'tty', input, output); + FS.createDevice(devFolder, 'null', function(){}, function(){}); // Create default streams. FS.streams[1] = { diff --git a/src/library_gl.js b/src/library_gl.js index ba99eaa8..1fa0cc9c 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -373,7 +373,7 @@ var LibraryGL = { glGetIntegerv__sig: 'vii', glGetIntegerv: function(name_, p) { - switch(name_) { // Handle a few trivial GLES values + switch(name_) { // Handle a few trivial GLES values case 0x8DFA: // GL_SHADER_COMPILER {{{ makeSetValue('p', '0', '1', 'i32') }}}; return; @@ -507,7 +507,7 @@ var LibraryGL = { glGenTextures__sig: 'vii', glGenTextures: function(n, textures) { for (var i = 0; i < n; i++) { - var id = GL.getNewId(GL.textures); + var id = GL.getNewId(GL.textures); GL.textures[id] = Module.ctx.createTexture(); {{{ makeSetValue('textures', 'i*4', 'id', 'i32') }}}; } @@ -726,7 +726,7 @@ var LibraryGL = { var ptable = GL.uniformTable[program]; if (!ptable) ptable = GL.uniformTable[program] = {}; var id = ptable[name]; - if (id) return id; + if (id) return id; var loc = Module.ctx.getUniformLocation(GL.programs[program], name); if (!loc) return -1; id = GL.getNewId(GL.uniforms); @@ -989,13 +989,15 @@ var LibraryGL = { glBindBuffer__sig: 'vii', glBindBuffer: function(target, buffer) { + var bufferObj = buffer ? GL.buffers[buffer] : null; + if (target == Module.ctx.ARRAY_BUFFER) { GL.currArrayBuffer = buffer; } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { GL.currElementArrayBuffer = buffer; } - Module.ctx.bindBuffer(target, buffer ? GL.buffers[buffer] : null); + Module.ctx.bindBuffer(target, bufferObj); }, glVertexAttrib1fv__sig: 'vii', @@ -1275,7 +1277,22 @@ var LibraryGL = { currentVao: null, enabledVertexAttribArrays: {}, // helps with vao cleanups + hasRunInit: false, + init: function() { + // Do not activate immediate/emulation code (e.g. replace glDrawElements) when in FULL_ES2 mode. + // We do not need full emulation, we instead emulate client-side arrays etc. in FULL_ES2 code in + // a straightforward manner, and avoid not having a bound buffer be ambiguous between es2 emulation + // code and legacy gl emulation code. +#if FULL_ES2 + return; +#endif + + if (GLEmulation.hasRunInit) { + return; + } + GLEmulation.hasRunInit = true; + GLEmulation.fogColor = new Float32Array(4); // Add some emulation workarounds @@ -1297,6 +1314,7 @@ var LibraryGL = { 0x80A0: 1 // GL_SAMPLE_COVERAGE }; + var glEnable = _glEnable; _glEnable = function(cap) { // Clean up the renderer on any change to the rendering state. The optimization of // skipping renderer setup is aimed at the case of multiple glDraw* right after each other @@ -1307,13 +1325,18 @@ var LibraryGL = { } else if (cap == 0x0de1 /* GL_TEXTURE_2D */) { // XXX not according to spec, and not in desktop GL, but works in some GLES1.x apparently, so support // it by forwarding to glEnableClientState + /* Actually, let's not, for now. (This sounds exceedingly broken) + * This is in gl_ps_workaround2.c. _glEnableClientState(cap); + */ return; } else if (!(cap in validCapabilities)) { return; } - Module.ctx.enable(cap); + glEnable(cap); }; + + var glDisable = _glDisable; _glDisable = function(cap) { if (GL.immediate.lastRenderer) GL.immediate.lastRenderer.cleanup(); if (cap == 0x0B60 /* GL_FOG */) { @@ -1322,12 +1345,15 @@ var LibraryGL = { } else if (cap == 0x0de1 /* GL_TEXTURE_2D */) { // XXX not according to spec, and not in desktop GL, but works in some GLES1.x apparently, so support // it by forwarding to glDisableClientState + /* Actually, let's not, for now. (This sounds exceedingly broken) + * This is in gl_ps_workaround2.c. _glDisableClientState(cap); + */ return; } else if (!(cap in validCapabilities)) { return; } - Module.ctx.disable(cap); + glDisable(cap); }; _glIsEnabled = function(cap) { if (cap == 0x0B60 /* GL_FOG */) { @@ -1453,6 +1479,7 @@ var LibraryGL = { _glShaderSource = function(shader, count, string, length) { var source = GL.getSource(shader, count, string, length); #if GL_DEBUG + console.log("glShaderSource: Input: \n" + source); GL.shaderOriginalSources[shader] = source; #endif // XXX We add attributes and uniforms to shaders. The program can ask for the # of them, and see the @@ -1510,9 +1537,7 @@ var LibraryGL = { } if (source.indexOf('gl_Color') >= 0) { source = 'attribute vec4 a_color; \n' + - 'uniform vec4 u_color; \n' + - 'uniform int u_hasColorAttrib; \n' + - source.replace(/gl_Color/g, '(u_hasColorAttrib > 0 ? a_color : u_color)'); + source.replace(/gl_Color/g, 'a_color'); } if (source.indexOf('gl_Normal') >= 0) { source = 'attribute vec3 a_normal; \n' + @@ -1558,6 +1583,7 @@ var LibraryGL = { } #if GL_DEBUG GL.shaderSources[shader] = source; + console.log("glShaderSource: Output: \n" + source); #endif Module.ctx.shaderSource(GL.shaders[shader], source); }; @@ -1706,8 +1732,12 @@ var LibraryGL = { getAttributeFromCapability: function(cap) { var attrib = null; switch (cap) { - case 0x8078: // GL_TEXTURE_COORD_ARRAY case 0x0de1: // GL_TEXTURE_2D - XXX not according to spec, and not in desktop GL, but works in some GLES1.x apparently, so support it +#if ASSERTIONS + abort("GL_TEXTURE_2D is not a spec-defined capability for gl{Enable,Disable}ClientState."); +#endif + // Fall through: + case 0x8078: // GL_TEXTURE_COORD_ARRAY attrib = GL.immediate.TEXTURE0 + GL.immediate.clientActiveTexture; break; case 0x8074: // GL_VERTEX_ARRAY attrib = GL.immediate.VERTEX; break; @@ -1767,19 +1797,19 @@ var LibraryGL = { case 'glEnableVertexAttribArray': ret = {{{ Functions.getIndex('_glEnableVertexAttribArray', true) }}}; break; case 'glDisableVertexAttribArray': ret = {{{ Functions.getIndex('_glDisableVertexAttribArray', true) }}}; break; case 'glVertexAttribPointer': ret = {{{ Functions.getIndex('_glVertexAttribPointer', true) }}}; break; - case 'glVertexAttrib1f': ret = {{{ Functions.getIndex('_glVertexAttrib1f', true) }}}; break; - case 'glVertexAttrib2f': ret = {{{ Functions.getIndex('_glVertexAttrib2f', true) }}}; break; - case 'glVertexAttrib3f': ret = {{{ Functions.getIndex('_glVertexAttrib3f', true) }}}; break; - case 'glVertexAttrib4f': ret = {{{ Functions.getIndex('_glVertexAttrib4f', true) }}}; break; - case 'glVertexAttrib1fv': ret = {{{ Functions.getIndex('_glVertexAttrib1fv', true) }}}; break; - case 'glVertexAttrib2fv': ret = {{{ Functions.getIndex('_glVertexAttrib2fv', true) }}}; break; - case 'glVertexAttrib3fv': ret = {{{ Functions.getIndex('_glVertexAttrib3fv', true) }}}; break; - case 'glVertexAttrib4fv': ret = {{{ Functions.getIndex('_glVertexAttrib4fv', true) }}}; break; - case 'glGetVertexAttribfv': ret = {{{ Functions.getIndex('_glGetVertexAttribfv', true) }}}; break; - case 'glGetVertexAttribiv': ret = {{{ Functions.getIndex('_glGetVertexAttribiv', true) }}}; break; - case 'glGetVertexAttribPointerv': ret = {{{ Functions.getIndex('_glGetVertexAttribPointerv', true) }}}; break; - case 'glGetAttribLocation': ret = {{{ Functions.getIndex('_glGetAttribLocation', true) }}}; break; - case 'glGetActiveAttrib': ret = {{{ Functions.getIndex('_glGetActiveAttrib', true) }}}; break; + case 'glVertexAttrib1f': ret = {{{ Functions.getIndex('_glVertexAttrib1f', true) }}}; break; + case 'glVertexAttrib2f': ret = {{{ Functions.getIndex('_glVertexAttrib2f', true) }}}; break; + case 'glVertexAttrib3f': ret = {{{ Functions.getIndex('_glVertexAttrib3f', true) }}}; break; + case 'glVertexAttrib4f': ret = {{{ Functions.getIndex('_glVertexAttrib4f', true) }}}; break; + case 'glVertexAttrib1fv': ret = {{{ Functions.getIndex('_glVertexAttrib1fv', true) }}}; break; + case 'glVertexAttrib2fv': ret = {{{ Functions.getIndex('_glVertexAttrib2fv', true) }}}; break; + case 'glVertexAttrib3fv': ret = {{{ Functions.getIndex('_glVertexAttrib3fv', true) }}}; break; + case 'glVertexAttrib4fv': ret = {{{ Functions.getIndex('_glVertexAttrib4fv', true) }}}; break; + case 'glGetVertexAttribfv': ret = {{{ Functions.getIndex('_glGetVertexAttribfv', true) }}}; break; + case 'glGetVertexAttribiv': ret = {{{ Functions.getIndex('_glGetVertexAttribiv', true) }}}; break; + case 'glGetVertexAttribPointerv': ret = {{{ Functions.getIndex('_glGetVertexAttribPointerv', true) }}}; break; + case 'glGetAttribLocation': ret = {{{ Functions.getIndex('_glGetAttribLocation', true) }}}; break; + case 'glGetActiveAttrib': ret = {{{ Functions.getIndex('_glGetActiveAttrib', true) }}}; break; case 'glBindRenderbuffer': ret = {{{ Functions.getIndex('_glBindRenderbuffer', true) }}}; break; case 'glDeleteRenderbuffers': ret = {{{ Functions.getIndex('_glDeleteRenderbuffers', true) }}}; break; case 'glGenRenderbuffers': ret = {{{ Functions.getIndex('_glGenRenderbuffers', true) }}}; break; @@ -1798,86 +1828,86 @@ var LibraryGL = { case 'glDeleteVertexArrays': ret = {{{ Functions.getIndex('_glDeleteVertexArrays', true) }}}; break; case 'glBindVertexArray': ret = {{{ Functions.getIndex('_glBindVertexArray', true) }}}; break; case 'glGetString': ret = {{{ Functions.getIndex('_glGetString', true) }}}; break; - case 'glBindTexture': ret = {{{ Functions.getIndex('_glBindTexture', true) }}}; break; - case 'glGetBufferParameteriv': ret = {{{ Functions.getIndex('_glGetBufferParameteriv', true) }}}; break; - case 'glIsBuffer': ret = {{{ Functions.getIndex('_glIsBuffer', true) }}}; break; - case 'glDeleteShader': ret = {{{ Functions.getIndex('_glDeleteShader', true) }}}; break; + case 'glBindTexture': ret = {{{ Functions.getIndex('_glBindTexture', true) }}}; break; + case 'glGetBufferParameteriv': ret = {{{ Functions.getIndex('_glGetBufferParameteriv', true) }}}; break; + case 'glIsBuffer': ret = {{{ Functions.getIndex('_glIsBuffer', true) }}}; break; + case 'glDeleteShader': ret = {{{ Functions.getIndex('_glDeleteShader', true) }}}; break; case 'glUniformMatrix2fv': ret = {{{ Functions.getIndex('_glUniformMatrix2fv', true) }}}; break; case 'glUniformMatrix3fv': ret = {{{ Functions.getIndex('_glUniformMatrix3fv', true) }}}; break; case 'glUniformMatrix4fv': ret = {{{ Functions.getIndex('_glUniformMatrix4fv', true) }}}; break; - case 'glIsRenderbuffer': ret = {{{ Functions.getIndex('_glIsRenderbuffer', true) }}}; break; - case 'glBlendEquation': ret = {{{ Functions.getIndex('_glBlendEquation', true) }}}; break; - case 'glBlendFunc': ret = {{{ Functions.getIndex('_glBlendFunc', true) }}}; break; - case 'glBlendFuncSeparate': ret = {{{ Functions.getIndex('_glBlendFuncSeparate', true) }}}; break; - case 'glBlendEquationSeparate': ret = {{{ Functions.getIndex('_glBlendEquationSeparate', true) }}}; break; - case 'glDepthRangef': ret = {{{ Functions.getIndex('_glDepthRangef', true) }}}; break; - case 'glClear': ret = {{{ Functions.getIndex('_glClear', true) }}}; break; - case 'glGenerateMipmap': ret = {{{ Functions.getIndex('_glGenerateMipmap', true) }}}; break; - case 'glBlendColor': ret = {{{ Functions.getIndex('_glBlendColor', true) }}}; break; - case 'glClearDepthf': ret = {{{ Functions.getIndex('_glClearDepthf', true) }}}; break; - case 'glDeleteProgram': ret = {{{ Functions.getIndex('_glDeleteProgram', true) }}}; break; - case 'glUniformMatrix3fv': ret = {{{ Functions.getIndex('_glUniformMatrix3fv', true) }}}; break; - case 'glClearColor': ret = {{{ Functions.getIndex('_glClearColor', true) }}}; break; - case 'glGetRenderbufferParameteriv': ret = {{{ Functions.getIndex('_glGetRenderbufferParameteriv', true) }}}; break; - case 'glGetShaderInfoLog': ret = {{{ Functions.getIndex('_glGetShaderInfoLog', true) }}}; break; - case 'glUniformMatrix4fv': ret = {{{ Functions.getIndex('_glUniformMatrix4fv', true) }}}; break; - case 'glClearStencil': ret = {{{ Functions.getIndex('_glClearStencil', true) }}}; break; - case 'glGetProgramInfoLog': ret = {{{ Functions.getIndex('_glGetProgramInfoLog', true) }}}; break; - case 'glGetUniformfv': ret = {{{ Functions.getIndex('_glGetUniformfv', true) }}}; break; - case 'glStencilFuncSeparate': ret = {{{ Functions.getIndex('_glStencilFuncSeparate', true) }}}; break; - case 'glSampleCoverage': ret = {{{ Functions.getIndex('_glSampleCoverage', true) }}}; break; - case 'glColorMask': ret = {{{ Functions.getIndex('_glColorMask', true) }}}; break; - case 'glGetShaderiv': ret = {{{ Functions.getIndex('_glGetShaderiv', true) }}}; break; - case 'glGetUniformiv': ret = {{{ Functions.getIndex('_glGetUniformiv', true) }}}; break; - case 'glCopyTexSubImage2D': ret = {{{ Functions.getIndex('_glCopyTexSubImage2D', true) }}}; break; - case 'glDetachShader': ret = {{{ Functions.getIndex('_glDetachShader', true) }}}; break; - case 'glGetShaderSource': ret = {{{ Functions.getIndex('_glGetShaderSource', true) }}}; break; - case 'glDeleteTextures': ret = {{{ Functions.getIndex('_glDeleteTextures', true) }}}; break; - case 'glGetAttachedShaders': ret = {{{ Functions.getIndex('_glGetAttachedShaders', true) }}}; break; - case 'glValidateProgram': ret = {{{ Functions.getIndex('_glValidateProgram', true) }}}; break; - case 'glDepthFunc': ret = {{{ Functions.getIndex('_glDepthFunc', true) }}}; break; - case 'glIsShader': ret = {{{ Functions.getIndex('_glIsShader', true) }}}; break; - case 'glDepthMask': ret = {{{ Functions.getIndex('_glDepthMask', true) }}}; break; - case 'glStencilMaskSeparate': ret = {{{ Functions.getIndex('_glStencilMaskSeparate', true) }}}; break; - case 'glIsProgram': ret = {{{ Functions.getIndex('_glIsProgram', true) }}}; break; - case 'glDisable': ret = {{{ Functions.getIndex('_glDisable', true) }}}; break; - case 'glStencilOpSeparate': ret = {{{ Functions.getIndex('_glStencilOpSeparate', true) }}}; break; - case 'glDrawArrays': ret = {{{ Functions.getIndex('_glDrawArrays', true) }}}; break; - case 'glDrawElements': ret = {{{ Functions.getIndex('_glDrawElements', true) }}}; break; - case 'glEnable': ret = {{{ Functions.getIndex('_glEnable', true) }}}; break; - case 'glFinish': ret = {{{ Functions.getIndex('_glFinish', true) }}}; break; - case 'glFlush': ret = {{{ Functions.getIndex('_glFlush', true) }}}; break; - case 'glFrontFace': ret = {{{ Functions.getIndex('_glFrontFace', true) }}}; break; - case 'glCullFace': ret = {{{ Functions.getIndex('_glCullFace', true) }}}; break; - case 'glGenTextures': ret = {{{ Functions.getIndex('_glGenTextures', true) }}}; break; - case 'glGetError': ret = {{{ Functions.getIndex('_glGetError', true) }}}; break; - case 'glGetIntegerv': ret = {{{ Functions.getIndex('_glGetIntegerv', true) }}}; break; - case 'glGetBooleanv': ret = {{{ Functions.getIndex('_glGetBooleanv', true) }}}; break; - case 'glGetFloatv': ret = {{{ Functions.getIndex('_glGetFloatv', true) }}}; break; - case 'glHint': ret = {{{ Functions.getIndex('_glHint', true) }}}; break; - case 'glIsTexture': ret = {{{ Functions.getIndex('_glIsTexture', true) }}}; break; - case 'glPixelStorei': ret = {{{ Functions.getIndex('_glPixelStorei', true) }}}; break; - case 'glReadPixels': ret = {{{ Functions.getIndex('_glReadPixels', true) }}}; break; - case 'glScissor': ret = {{{ Functions.getIndex('_glScissor', true) }}}; break; - case 'glStencilFunc': ret = {{{ Functions.getIndex('_glStencilFunc', true) }}}; break; - case 'glStencilMask': ret = {{{ Functions.getIndex('_glStencilMask', true) }}}; break; - case 'glStencilOp': ret = {{{ Functions.getIndex('_glStencilOp', true) }}}; break; - case 'glTexImage2D': ret = {{{ Functions.getIndex('_glTexImage2D', true) }}}; break; - case 'glTexParameterf': ret = {{{ Functions.getIndex('_glTexParameterf', true) }}}; break; - case 'glTexParameterfv': ret = {{{ Functions.getIndex('_glTexParameterfv', true) }}}; break; - case 'glTexParameteri': ret = {{{ Functions.getIndex('_glTexParameteri', true) }}}; break; - case 'glTexParameteriv': ret = {{{ Functions.getIndex('_glTexParameteriv', true) }}}; break; - case 'glGetTexParameterfv': ret = {{{ Functions.getIndex('_glGetTexParameterfv', true) }}}; break; - case 'glGetTexParameteriv': ret = {{{ Functions.getIndex('_glGetTexParameteriv', true) }}}; break; - case 'glTexSubImage2D': ret = {{{ Functions.getIndex('_glTexSubImage2D', true) }}}; break; - case 'glCopyTexImage2D': ret = {{{ Functions.getIndex('_glCopyTexImage2D', true) }}}; break; - case 'glViewport': ret = {{{ Functions.getIndex('_glViewport', true) }}}; break; - case 'glIsEnabled': ret = {{{ Functions.getIndex('_glIsEnabled', true) }}}; break; - case 'glLineWidth': ret = {{{ Functions.getIndex('_glLineWidth', true) }}}; break; - case 'glPolygonOffset': ret = {{{ Functions.getIndex('_glPolygonOffset', true) }}}; break; - case 'glReleaseShaderCompiler': ret = {{{ Functions.getIndex('_glReleaseShaderCompiler', true) }}}; break; - case 'glGetShaderPrecisionFormat': ret = {{{ Functions.getIndex('_glGetShaderPrecisionFormat', true) }}}; break; - case 'glShaderBinary': ret = {{{ Functions.getIndex('_glShaderBinary', true) }}}; break; + case 'glIsRenderbuffer': ret = {{{ Functions.getIndex('_glIsRenderbuffer', true) }}}; break; + case 'glBlendEquation': ret = {{{ Functions.getIndex('_glBlendEquation', true) }}}; break; + case 'glBlendFunc': ret = {{{ Functions.getIndex('_glBlendFunc', true) }}}; break; + case 'glBlendFuncSeparate': ret = {{{ Functions.getIndex('_glBlendFuncSeparate', true) }}}; break; + case 'glBlendEquationSeparate': ret = {{{ Functions.getIndex('_glBlendEquationSeparate', true) }}}; break; + case 'glDepthRangef': ret = {{{ Functions.getIndex('_glDepthRangef', true) }}}; break; + case 'glClear': ret = {{{ Functions.getIndex('_glClear', true) }}}; break; + case 'glGenerateMipmap': ret = {{{ Functions.getIndex('_glGenerateMipmap', true) }}}; break; + case 'glBlendColor': ret = {{{ Functions.getIndex('_glBlendColor', true) }}}; break; + case 'glClearDepthf': ret = {{{ Functions.getIndex('_glClearDepthf', true) }}}; break; + case 'glDeleteProgram': ret = {{{ Functions.getIndex('_glDeleteProgram', true) }}}; break; + case 'glUniformMatrix3fv': ret = {{{ Functions.getIndex('_glUniformMatrix3fv', true) }}}; break; + case 'glClearColor': ret = {{{ Functions.getIndex('_glClearColor', true) }}}; break; + case 'glGetRenderbufferParameteriv': ret = {{{ Functions.getIndex('_glGetRenderbufferParameteriv', true) }}}; break; + case 'glGetShaderInfoLog': ret = {{{ Functions.getIndex('_glGetShaderInfoLog', true) }}}; break; + case 'glUniformMatrix4fv': ret = {{{ Functions.getIndex('_glUniformMatrix4fv', true) }}}; break; + case 'glClearStencil': ret = {{{ Functions.getIndex('_glClearStencil', true) }}}; break; + case 'glGetProgramInfoLog': ret = {{{ Functions.getIndex('_glGetProgramInfoLog', true) }}}; break; + case 'glGetUniformfv': ret = {{{ Functions.getIndex('_glGetUniformfv', true) }}}; break; + case 'glStencilFuncSeparate': ret = {{{ Functions.getIndex('_glStencilFuncSeparate', true) }}}; break; + case 'glSampleCoverage': ret = {{{ Functions.getIndex('_glSampleCoverage', true) }}}; break; + case 'glColorMask': ret = {{{ Functions.getIndex('_glColorMask', true) }}}; break; + case 'glGetShaderiv': ret = {{{ Functions.getIndex('_glGetShaderiv', true) }}}; break; + case 'glGetUniformiv': ret = {{{ Functions.getIndex('_glGetUniformiv', true) }}}; break; + case 'glCopyTexSubImage2D': ret = {{{ Functions.getIndex('_glCopyTexSubImage2D', true) }}}; break; + case 'glDetachShader': ret = {{{ Functions.getIndex('_glDetachShader', true) }}}; break; + case 'glGetShaderSource': ret = {{{ Functions.getIndex('_glGetShaderSource', true) }}}; break; + case 'glDeleteTextures': ret = {{{ Functions.getIndex('_glDeleteTextures', true) }}}; break; + case 'glGetAttachedShaders': ret = {{{ Functions.getIndex('_glGetAttachedShaders', true) }}}; break; + case 'glValidateProgram': ret = {{{ Functions.getIndex('_glValidateProgram', true) }}}; break; + case 'glDepthFunc': ret = {{{ Functions.getIndex('_glDepthFunc', true) }}}; break; + case 'glIsShader': ret = {{{ Functions.getIndex('_glIsShader', true) }}}; break; + case 'glDepthMask': ret = {{{ Functions.getIndex('_glDepthMask', true) }}}; break; + case 'glStencilMaskSeparate': ret = {{{ Functions.getIndex('_glStencilMaskSeparate', true) }}}; break; + case 'glIsProgram': ret = {{{ Functions.getIndex('_glIsProgram', true) }}}; break; + case 'glDisable': ret = {{{ Functions.getIndex('_glDisable', true) }}}; break; + case 'glStencilOpSeparate': ret = {{{ Functions.getIndex('_glStencilOpSeparate', true) }}}; break; + case 'glDrawArrays': ret = {{{ Functions.getIndex('_glDrawArrays', true) }}}; break; + case 'glDrawElements': ret = {{{ Functions.getIndex('_glDrawElements', true) }}}; break; + case 'glEnable': ret = {{{ Functions.getIndex('_glEnable', true) }}}; break; + case 'glFinish': ret = {{{ Functions.getIndex('_glFinish', true) }}}; break; + case 'glFlush': ret = {{{ Functions.getIndex('_glFlush', true) }}}; break; + case 'glFrontFace': ret = {{{ Functions.getIndex('_glFrontFace', true) }}}; break; + case 'glCullFace': ret = {{{ Functions.getIndex('_glCullFace', true) }}}; break; + case 'glGenTextures': ret = {{{ Functions.getIndex('_glGenTextures', true) }}}; break; + case 'glGetError': ret = {{{ Functions.getIndex('_glGetError', true) }}}; break; + case 'glGetIntegerv': ret = {{{ Functions.getIndex('_glGetIntegerv', true) }}}; break; + case 'glGetBooleanv': ret = {{{ Functions.getIndex('_glGetBooleanv', true) }}}; break; + case 'glGetFloatv': ret = {{{ Functions.getIndex('_glGetFloatv', true) }}}; break; + case 'glHint': ret = {{{ Functions.getIndex('_glHint', true) }}}; break; + case 'glIsTexture': ret = {{{ Functions.getIndex('_glIsTexture', true) }}}; break; + case 'glPixelStorei': ret = {{{ Functions.getIndex('_glPixelStorei', true) }}}; break; + case 'glReadPixels': ret = {{{ Functions.getIndex('_glReadPixels', true) }}}; break; + case 'glScissor': ret = {{{ Functions.getIndex('_glScissor', true) }}}; break; + case 'glStencilFunc': ret = {{{ Functions.getIndex('_glStencilFunc', true) }}}; break; + case 'glStencilMask': ret = {{{ Functions.getIndex('_glStencilMask', true) }}}; break; + case 'glStencilOp': ret = {{{ Functions.getIndex('_glStencilOp', true) }}}; break; + case 'glTexImage2D': ret = {{{ Functions.getIndex('_glTexImage2D', true) }}}; break; + case 'glTexParameterf': ret = {{{ Functions.getIndex('_glTexParameterf', true) }}}; break; + case 'glTexParameterfv': ret = {{{ Functions.getIndex('_glTexParameterfv', true) }}}; break; + case 'glTexParameteri': ret = {{{ Functions.getIndex('_glTexParameteri', true) }}}; break; + case 'glTexParameteriv': ret = {{{ Functions.getIndex('_glTexParameteriv', true) }}}; break; + case 'glGetTexParameterfv': ret = {{{ Functions.getIndex('_glGetTexParameterfv', true) }}}; break; + case 'glGetTexParameteriv': ret = {{{ Functions.getIndex('_glGetTexParameteriv', true) }}}; break; + case 'glTexSubImage2D': ret = {{{ Functions.getIndex('_glTexSubImage2D', true) }}}; break; + case 'glCopyTexImage2D': ret = {{{ Functions.getIndex('_glCopyTexImage2D', true) }}}; break; + case 'glViewport': ret = {{{ Functions.getIndex('_glViewport', true) }}}; break; + case 'glIsEnabled': ret = {{{ Functions.getIndex('_glIsEnabled', true) }}}; break; + case 'glLineWidth': ret = {{{ Functions.getIndex('_glLineWidth', true) }}}; break; + case 'glPolygonOffset': ret = {{{ Functions.getIndex('_glPolygonOffset', true) }}}; break; + case 'glReleaseShaderCompiler': ret = {{{ Functions.getIndex('_glReleaseShaderCompiler', true) }}}; break; + case 'glGetShaderPrecisionFormat': ret = {{{ Functions.getIndex('_glGetShaderPrecisionFormat', true) }}}; break; + case 'glShaderBinary': ret = {{{ Functions.getIndex('_glShaderBinary', true) }}}; break; } if (!ret) Module.printErr('WARNING: getProcAddress failed for ' + name); return ret; @@ -1960,10 +1990,879 @@ var LibraryGL = { // GL Immediate mode + // See comment in GLEmulation.init() +#if FULL_ES2 == 0 $GLImmediate__postset: 'GL.immediate.setupFuncs(); Browser.moduleContextCreatedCallbacks.push(function() { GL.immediate.init() });', +#endif $GLImmediate__deps: ['$Browser', '$GL', '$GLEmulation'], $GLImmediate: { - MAX_TEXTURES: 7, + MapTreeLib: null, + spawnMapTreeLib: function() { + /* A naive implementation of a map backed by an array, and accessed by + * naive iteration along the array. (hashmap with only one bucket) + */ + function CNaiveListMap() { + var list = []; + + this.insert = function(key, val) { + if (this.contains(key|0)) return false; + list.push([key, val]); + return true; + }; + + var __contains_i; + this.contains = function(key) { + for (__contains_i = 0; __contains_i < list.length; ++__contains_i) { + if (list[__contains_i][0] === key) return true; + } + return false; + }; + + var __get_i; + this.get = function(key) { + for (__get_i = 0; __get_i < list.length; ++__get_i) { + if (list[__get_i][0] === key) return list[__get_i][1]; + } + return undefined; + }; + }; + + /* A tree of map nodes. + Uses `KeyView`s to allow descending the tree without garbage. + Example: { + // Create our map object. + var map = new ObjTreeMap(); + + // Grab the static keyView for the map. + var keyView = map.GetStaticKeyView(); + + // Let's make a map for: + // root: <undefined> + // 1: <undefined> + // 2: <undefined> + // 5: "Three, sir!" + // 3: "Three!" + + // Note how we can chain together `Reset` and `Next` to + // easily descend based on multiple key fragments. + keyView.Reset().Next(1).Next(2).Next(5).Set("Three, sir!"); + keyView.Reset().Next(1).Next(2).Next(3).Set("Three!"); + } + */ + function CMapTree() { + function CNLNode() { + var map = new CNaiveListMap(); + + this.child = function(keyFrag) { + if (!map.contains(keyFrag|0)) { + map.insert(keyFrag|0, new CNLNode()); + } + return map.get(keyFrag|0); + }; + + this.value = undefined; + this.get = function() { + return this.value; + }; + + this.set = function(val) { + this.value = val; + }; + } + + function CKeyView(root) { + var cur; + + this.reset = function() { + cur = root; + return this; + }; + this.reset(); + + this.next = function(keyFrag) { + cur = cur.child(keyFrag); + return this; + }; + + this.get = function() { + return cur.get(); + }; + + this.set = function(val) { + cur.set(val); + }; + }; + + var root; + var staticKeyView; + + this.createKeyView = function() { + return new CKeyView(root); + } + + this.clear = function() { + root = new CNLNode(); + staticKeyView = this.createKeyView(); + }; + this.clear(); + + this.getStaticKeyView = function() { + staticKeyView.reset(); + return staticKeyView; + }; + }; + + // Exports: + return { + create: function() { + return new CMapTree(); + }, + }; + }, + + TexEnvJIT: null, + spawnTexEnvJIT: function() { + // GL defs: + var GL_TEXTURE0 = 0x84C0; + var GL_TEXTURE_1D = 0x0DE0; + var GL_TEXTURE_2D = 0x0DE1; + var GL_TEXTURE_3D = 0x806f; + var GL_TEXTURE_CUBE_MAP = 0x8513; + var GL_TEXTURE_ENV = 0x2300; + var GL_TEXTURE_ENV_MODE = 0x2200; + var GL_TEXTURE_ENV_COLOR = 0x2201; + var GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; + var GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; + var GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; + var GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; + var GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; + var GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A; + + var GL_SRC0_RGB = 0x8580; + var GL_SRC1_RGB = 0x8581; + var GL_SRC2_RGB = 0x8582; + + var GL_SRC0_ALPHA = 0x8588; + var GL_SRC1_ALPHA = 0x8589; + var GL_SRC2_ALPHA = 0x858A; + + var GL_OPERAND0_RGB = 0x8590; + var GL_OPERAND1_RGB = 0x8591; + var GL_OPERAND2_RGB = 0x8592; + + var GL_OPERAND0_ALPHA = 0x8598; + var GL_OPERAND1_ALPHA = 0x8599; + var GL_OPERAND2_ALPHA = 0x859A; + + var GL_COMBINE_RGB = 0x8571; + var GL_COMBINE_ALPHA = 0x8572; + + var GL_RGB_SCALE = 0x8573; + var GL_ALPHA_SCALE = 0x0D1C; + + // env.mode + var GL_ADD = 0x0104; + var GL_BLEND = 0x0BE2; + var GL_REPLACE = 0x1E01; + var GL_MODULATE = 0x2100; + var GL_DECAL = 0x2101; + var GL_COMBINE = 0x8570; + + // env.color/alphaCombiner + //var GL_ADD = 0x0104; + //var GL_REPLACE = 0x1E01; + //var GL_MODULATE = 0x2100; + var GL_SUBTRACT = 0x84E7; + var GL_INTERPOLATE = 0x8575; + + // env.color/alphaSrc + var GL_TEXTURE = 0x1702; + var GL_CONSTANT = 0x8576; + var GL_PRIMARY_COLOR = 0x8577; + var GL_PREVIOUS = 0x8578; + + // env.color/alphaOp + var GL_SRC_COLOR = 0x0300; + var GL_ONE_MINUS_SRC_COLOR = 0x0301; + var GL_SRC_ALPHA = 0x0302; + var GL_ONE_MINUS_SRC_ALPHA = 0x0303; + + var GL_RGB = 0x1907; + var GL_RGBA = 0x1908; + + // Our defs: + var TEXENVJIT_NAMESPACE_PREFIX = "tej_"; + // Not actually constant, as they can be changed between JIT passes: + var TEX_UNIT_UNIFORM_PREFIX = "uTexUnit"; + var TEX_COORD_VARYING_PREFIX = "vTexCoord"; + var PRIM_COLOR_VARYING = "vPrimColor"; + var TEX_MATRIX_UNIFORM_PREFIX = "uTexMatrix"; + + // Static vars: + var s_texUnits = null; //[]; + var s_activeTexture = 0; + + var s_requiredTexUnitsForPass = []; + + // Static funcs: + function abort(info) { + assert(false, "[TexEnvJIT] ABORT: " + info); + } + + function abort_noSupport(info) { + abort("No support: " + info); + } + + function abort_sanity(info) { + abort("Sanity failure: " + info); + } + + function genTexUnitSampleExpr(texUnitID) { + var texUnit = s_texUnits[texUnitID]; + var texType = texUnit.getTexType(); + + var func = null; + switch (texType) { + case GL_TEXTURE_1D: + func = "texture2D"; + break; + case GL_TEXTURE_2D: + func = "texture2D"; + break; + case GL_TEXTURE_3D: + return abort_noSupport("No support for 3D textures."); + case GL_TEXTURE_CUBE_MAP: + func = "textureCube"; + break; + default: + return abort_sanity("Unknown texType: 0x" + texType.toString(16)); + } + + var texCoordExpr = TEX_COORD_VARYING_PREFIX + texUnitID; + if (TEX_MATRIX_UNIFORM_PREFIX != null) { + texCoordExpr = "(" + TEX_MATRIX_UNIFORM_PREFIX + texUnitID + " * " + texCoordExpr + ")"; + } + return func + "(" + TEX_UNIT_UNIFORM_PREFIX + texUnitID + ", " + texCoordExpr + ".xy)"; + } + + function getTypeFromCombineOp(op) { + switch (op) { + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + return "vec3"; + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + return "float"; + } + + return Abort_NoSupport("Unsupported combiner op: 0x" + op.toString(16)); + } + + function getCurTexUnit() { + return s_texUnits[s_activeTexture]; + } + + function genCombinerSourceExpr(texUnitID, constantExpr, previousVar, + src, op) + { + var srcExpr = null; + switch (src) { + case GL_TEXTURE: + srcExpr = genTexUnitSampleExpr(texUnitID); + break; + case GL_CONSTANT: + srcExpr = constantExpr; + break; + case GL_PRIMARY_COLOR: + srcExpr = PRIM_COLOR_VARYING; + break; + case GL_PREVIOUS: + srcExpr = previousVar; + break; + default: + return abort_noSupport("Unsupported combiner src: 0x" + src.toString(16)); + } + + var expr = null; + switch (op) { + case GL_SRC_COLOR: + expr = srcExpr + ".rgb"; + break; + case GL_ONE_MINUS_SRC_COLOR: + expr = "(vec3(1.0) - " + srcExpr + ".rgb)"; + break; + case GL_SRC_ALPHA: + expr = srcExpr + ".a"; + break; + case GL_ONE_MINUS_SRC_ALPHA: + expr = "(1.0 - " + srcExpr + ".a)"; + break; + default: + return abort_noSupport("Unsupported combiner op: 0x" + op.toString(16)); + } + + return expr; + } + + function valToFloatLiteral(val) { + if (val == Math.round(val)) return val + '.0'; + return val; + } + + + // Classes: + function CTexEnv() { + this.mode = GL_MODULATE; + this.colorCombiner = GL_MODULATE; + this.alphaCombiner = GL_MODULATE; + this.colorScale = 1; + this.alphaScale = 1; + this.envColor = [0, 0, 0, 0]; + + this.colorSrc = [ + GL_TEXTURE, + GL_PREVIOUS, + GL_CONSTANT + ]; + this.alphaSrc = [ + GL_TEXTURE, + GL_PREVIOUS, + GL_CONSTANT + ]; + this.colorOp = [ + GL_SRC_COLOR, + GL_SRC_COLOR, + GL_SRC_ALPHA + ]; + this.alphaOp = [ + GL_SRC_ALPHA, + GL_SRC_ALPHA, + GL_SRC_ALPHA + ]; + + this.traverseState = function(keyView) { + keyView.next(this.mode); + keyView.next(this.colorCombiner); + keyView.next(this.alphaCombiner); + keyView.next(this.colorCombiner); + keyView.next(this.alphaScale); + keyView.next(this.envColor[0]); + keyView.next(this.envColor[1]); + keyView.next(this.envColor[2]); + keyView.next(this.envColor[3]); + + keyView.next(this.colorSrc[0]); + keyView.next(this.colorSrc[1]); + keyView.next(this.colorSrc[2]); + + keyView.next(this.alphaSrc[0]); + keyView.next(this.alphaSrc[1]); + keyView.next(this.alphaSrc[2]); + + keyView.next(this.colorOp[0]); + keyView.next(this.colorOp[1]); + keyView.next(this.colorOp[2]); + + keyView.next(this.alphaOp[0]); + keyView.next(this.alphaOp[1]); + keyView.next(this.alphaOp[2]); + }; + } + + function CTexUnit() { + this.env = new CTexEnv(); + this.enabled_tex1D = false; + this.enabled_tex2D = false; + this.enabled_tex3D = false; + this.enabled_texCube = false; + + this.traverseState = function(keyView) { + var texUnitType = this.getTexType(); + keyView.next(texUnitType); + if (!texUnitType) return; + this.env.traverseState(keyView); + }; + }; + + // Class impls: + CTexUnit.prototype.enabled = function() { + return this.getTexType() != 0; + } + + CTexUnit.prototype.genPassLines = function(passOutputVar, passInputVar, texUnitID) { + if (!this.enabled()) { + return ["vec4 " + passOutputVar + " = " + passInputVar + ";"]; + } + + return this.env.genPassLines(passOutputVar, passInputVar, texUnitID); + } + + CTexUnit.prototype.getTexType = function() { + if (this.enabled_texCube) { + return GL_TEXTURE_CUBE_MAP; + } else if (this.enabled_tex3D) { + return GL_TEXTURE_3D; + } else if (this.enabled_tex2D) { + return GL_TEXTURE_2D; + } else if (this.enabled_tex1D) { + return GL_TEXTURE_1D; + } + return 0; + } + + CTexEnv.prototype.genPassLines = function(passOutputVar, passInputVar, texUnitID) { + switch (this.mode) { + case GL_REPLACE: { + /* RGB: + * Cv = Cs + * Av = Ap // Note how this is different, and that we'll + * need to track the bound texture internalFormat + * to get this right. + * + * RGBA: + * Cv = Cs + * Av = As + */ + return [ + "vec4 " + passOutputVar + " = " + genTexUnitSampleExpr(texUnitID) + ";", + ]; + } + case GL_ADD: { + /* RGBA: + * Cv = Cp + Cs + * Av = ApAs + */ + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var texVar = prefix + "tex"; + var colorVar = prefix + "color"; + var alphaVar = prefix + "alpha"; + + return [ + "vec4 " + texVar + " = " + genTexUnitSampleExpr(texUnitID) + ";", + "vec3 " + colorVar + " = " + passInputVar + ".rgb + " + texVar + ".rgb;", + "float " + alphaVar + " = " + passInputVar + ".a * " + texVar + ".a;", + "vec4 " + passOutputVar + " = vec4(" + colorVar + ", " + alphaVar + ");", + ]; + } + case GL_MODULATE: { + /* RGBA: + * Cv = CpCs + * Av = ApAs + */ + var line = [ + "vec4 " + passOutputVar, + " = ", + passInputVar, + " * ", + genTexUnitSampleExpr(texUnitID), + ";", + ]; + return [line.join("")]; + } + case GL_DECAL: { + /* RGBA: + * Cv = Cp(1 - As) + CsAs + * Av = Ap + */ + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var texVar = prefix + "tex"; + var colorVar = prefix + "color"; + var alphaVar = prefix + "alpha"; + + return [ + "vec4 " + texVar + " = " + genTexUnitSampleExpr(texUnitID) + ";", + [ + "vec3 " + colorVar + " = ", + passInputVar + ".rgb * (1.0 - " + texVar + ".a)", + " + ", + texVar + ".rgb * " + texVar + ".a", + ";" + ].join(""), + "float " + alphaVar + " = " + passInputVar + ".a;", + "vec4 " + passOutputVar + " = vec4(" + colorVar + ", " + alphaVar + ");", + ]; + } + case GL_BLEND: { + /* RGBA: + * Cv = Cp(1 - Cs) + CcCs + * Av = As + */ + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var texVar = prefix + "tex"; + var colorVar = prefix + "color"; + var alphaVar = prefix + "alpha"; + + return [ + "vec4 " + texVar + " = " + genTexUnitSampleExpr(texUnitID) + ";", + [ + "vec3 " + colorVar + " = ", + passInputVar + ".rgb * (1.0 - " + texVar + ".rgb)", + " + ", + PRIM_COLOR_VARYING + ".rgb * " + texVar + ".rgb", + ";" + ].join(""), + "float " + alphaVar + " = " + texVar + ".a;", + "vec4 " + passOutputVar + " = vec4(" + colorVar + ", " + alphaVar + ");", + ]; + } + case GL_COMBINE: { + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var colorVar = prefix + "color"; + var alphaVar = prefix + "alpha"; + var colorLines = this.genCombinerLines(true, colorVar, + passInputVar, texUnitID, + this.colorCombiner, this.colorSrc, this.colorOp); + var alphaLines = this.genCombinerLines(false, alphaVar, + passInputVar, texUnitID, + this.alphaCombiner, this.alphaSrc, this.alphaOp); + var line = [ + "vec4 " + passOutputVar, + " = ", + "vec4(", + colorVar + " * " + valToFloatLiteral(this.colorScale), + ", ", + alphaVar + " * " + valToFloatLiteral(this.alphaScale), + ")", + ";", + ].join(""); + return [].concat(colorLines, alphaLines, [line]); + } + } + + return Abort_NoSupport("Unsupported TexEnv mode: 0x" + this.mode.toString(16)); + } + + CTexEnv.prototype.genCombinerLines = function(isColor, outputVar, + passInputVar, texUnitID, + combiner, srcArr, opArr) + { + var argsNeeded = null; + switch (combiner) { + case GL_REPLACE: + argsNeeded = 1; + break; + + case GL_MODULATE: + case GL_ADD: + case GL_SUBTRACT: + argsNeeded = 2; + break; + + case GL_INTERPOLATE: + argsNeeded = 3; + break; + + default: + return abort_noSupport("Unsupported combiner: 0x" + combiner.toString(16)); + } + + var constantExpr = [ + "vec4(", + valToFloatLiteral(this.envColor[0]), + ", ", + valToFloatLiteral(this.envColor[1]), + ", ", + valToFloatLiteral(this.envColor[2]), + ", ", + valToFloatLiteral(this.envColor[3]), + ")", + ].join(""); + var src0Expr = (argsNeeded >= 1) ? genCombinerSourceExpr(texUnitID, constantExpr, passInputVar, srcArr[0], opArr[0]) + : null; + var src1Expr = (argsNeeded >= 2) ? genCombinerSourceExpr(texUnitID, constantExpr, passInputVar, srcArr[1], opArr[1]) + : null; + var src2Expr = (argsNeeded >= 3) ? genCombinerSourceExpr(texUnitID, constantExpr, passInputVar, srcArr[2], opArr[2]) + : null; + + var outputType = isColor ? "vec3" : "float"; + var lines = null; + switch (combiner) { + case GL_REPLACE: { + var line = [ + outputType + " " + outputVar, + " = ", + src0Expr, + ";", + ]; + lines = [line.join("")]; + break; + } + case GL_MODULATE: { + var line = [ + outputType + " " + outputVar + " = ", + src0Expr + " * " + src1Expr, + ";", + ]; + lines = [line.join("")]; + break; + } + case GL_ADD: { + var line = [ + outputType + " " + outputVar + " = ", + src0Expr + " + " + src1Expr, + ";", + ]; + lines = [line.join("")]; + break; + } + case GL_SUBTRACT: { + var line = [ + outputType + " " + outputVar + " = ", + src0Expr + " - " + src1Expr, + ";", + ]; + lines = [line.join("")]; + break; + } + case GL_INTERPOLATE: { + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + texUnitID + "_"; + var arg2Var = prefix + "colorSrc2"; + var arg2Line = getTypeFromCombineOp(this.colorOp[2]) + " " + arg2Var + " = " + src2Expr + ";"; + + var line = [ + outputType + " " + outputVar, + " = ", + src0Expr + " * " + arg2Var, + " + ", + src1Expr + " * (1.0 - " + arg2Var + ")", + ";", + ]; + lines = [ + arg2Line, + line.join(""), + ]; + break; + } + + default: + return abort_sanity("Unmatched TexEnv.colorCombiner?"); + } + + return lines; + } + + return { + // Exports: + init: function(gl, specifiedMaxTextureImageUnits) { + var maxTexUnits = 0; + if (specifiedMaxTextureImageUnits) { + maxTexUnits = specifiedMaxTextureImageUnits; + } else if (gl) { + maxTexUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + } + + assert(maxTexUnits > 0); + + s_texUnits = []; + for (var i = 0; i < maxTexUnits; i++) { + s_texUnits.push(new CTexUnit()); + } + }, + + setGLSLVars: function(uTexUnitPrefix, vTexCoordPrefix, vPrimColor, uTexMatrixPrefix) { + TEX_UNIT_UNIFORM_PREFIX = uTexUnitPrefix; + TEX_COORD_VARYING_PREFIX = vTexCoordPrefix; + PRIM_COLOR_VARYING = vPrimColor; + TEX_MATRIX_UNIFORM_PREFIX = uTexMatrixPrefix; + }, + + genAllPassLines: function(resultDest, indentSize) { + indentSize = indentSize || 0; + + s_requiredTexUnitsForPass.length = 0; // Clear the list. + var lines = []; + var lastPassVar = PRIM_COLOR_VARYING; + for (var i = 0; i < s_texUnits.length; i++) { + if (!s_texUnits[i].enabled()) continue; + + s_requiredTexUnitsForPass.push(i); + + var prefix = TEXENVJIT_NAMESPACE_PREFIX + 'env' + i + "_"; + var passOutputVar = prefix + "result"; + + var newLines = s_texUnits[i].genPassLines(passOutputVar, lastPassVar, i); + lines = lines.concat(newLines, [""]); + + lastPassVar = passOutputVar; + } + lines.push(resultDest + " = " + lastPassVar + ";"); + + var indent = ""; + for (var i = 0; i < indentSize; i++) indent += " "; + + var output = indent + lines.join("\n" + indent); + + return output; + }, + + getUsedTexUnitList: function() { + return s_requiredTexUnitsForPass; + }, + + traverseState: function(keyView) { + for (var i = 0; i < s_texUnits.length; i++) { + var texUnit = s_texUnits[i]; + var enabled = texUnit.enabled(); + keyView.next(enabled); + if (enabled) { + texUnit.traverseState(keyView); + } + } + }, + + getTexUnitType: function(texUnitID) { + assert(texUnitID >= 0 && + texUnitID < s_texUnits.length); + + return s_texUnits[texUnitID].getTexType(); + }, + + // Hooks: + hook_activeTexture: function(texture) { + s_activeTexture = texture - GL_TEXTURE0; + }, + + hook_enable: function(cap) { + var cur = getCurTexUnit(); + switch (cap) { + case GL_TEXTURE_1D: + cur.enabled_tex1D = true; + break; + case GL_TEXTURE_2D: + cur.enabled_tex2D = true; + break; + case GL_TEXTURE_3D: + cur.enabled_tex3D = true; + break; + case GL_TEXTURE_CUBE_MAP: + cur.enabled_texCube = true; + break; + } + }, + + hook_disable: function(cap) { + var cur = getCurTexUnit(); + switch (cap) { + case GL_TEXTURE_1D: + cur.enabled_tex1D = false; + break; + case GL_TEXTURE_2D: + cur.enabled_tex2D = false; + break; + case GL_TEXTURE_3D: + cur.enabled_tex3D = false; + break; + case GL_TEXTURE_CUBE_MAP: + cur.enabled_texCube = false; + break; + } + }, + + hook_texEnvf: function(target, pname, param) { + if (target != GL_TEXTURE_ENV) + return; + + var env = getCurTexUnit().env; + switch (pname) { + case GL_RGB_SCALE: + env.colorScale = param; + break; + case GL_ALPHA_SCALE: + env.alphaScale = param; + break; + + default: + Module.printErr('WARNING: Unhandled `pname` in call to `glTexEnvf`.'); + } + }, + + hook_texEnvi: function(target, pname, param) { + if (target != GL_TEXTURE_ENV) + return; + + var env = getCurTexUnit().env; + switch (pname) { + case GL_TEXTURE_ENV_MODE: + env.mode = param; + break; + + case GL_COMBINE_RGB: + env.colorCombiner = param; + break; + case GL_COMBINE_ALPHA: + env.alphaCombiner = param; + break; + + case GL_SRC0_RGB: + env.colorSrc[0] = param; + break; + case GL_SRC1_RGB: + env.colorSrc[1] = param; + break; + case GL_SRC2_RGB: + env.colorSrc[2] = param; + break; + + case GL_SRC0_ALPHA: + env.alphaSrc[0] = param; + break; + case GL_SRC1_ALPHA: + env.alphaSrc[1] = param; + break; + case GL_SRC2_ALPHA: + env.alphaSrc[2] = param; + break; + + case GL_OPERAND0_RGB: + env.colorOp[0] = param; + break; + case GL_OPERAND1_RGB: + env.colorOp[1] = param; + break; + case GL_OPERAND2_RGB: + env.colorOp[2] = param; + break; + + case GL_OPERAND0_ALPHA: + env.alphaOp[0] = param; + break; + case GL_OPERAND1_ALPHA: + env.alphaOp[1] = param; + break; + case GL_OPERAND2_ALPHA: + env.alphaOp[2] = param; + break; + + case GL_RGB_SCALE: + env.colorScale = param; + break; + case GL_ALPHA_SCALE: + env.alphaScale = param; + break; + + default: + Module.printErr('WARNING: Unhandled `pname` in call to `glTexEnvi`.'); + } + }, + + hook_texEnvfv: function(target, pname, params) { + if (target != GL_TEXTURE_ENV) return; + + var env = getCurTexUnit().env; + switch (pname) { + case GL_TEXTURE_ENV_COLOR: { + for (var i = 0; i < 4; i++) { + var param = {{{ makeGetValue('params', 'i*4', 'float') }}}; + env.envColor[i] = param; + } + break + } + default: + Module.printErr('WARNING: Unhandled `pname` in call to `glTexEnvfv`.'); + } + }, + }; + }, // Vertex and index data vertexData: null, // current vertex data. either tempData (glBegin etc.) or a view into the heap (gl*Pointer). Default view is F32 @@ -1974,7 +2873,6 @@ var LibraryGL = { mode: -1, rendererCache: null, - rendererCacheItemTemplate: [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null], // 16 nulls rendererComponents: [], // small cache for calls inside glBegin/end. counts how many times the element was seen rendererComponentPointer: 0, // next place to start a glBegin/end component lastRenderer: null, // used to avoid cleaning up and re-preparing the same renderer @@ -1988,6 +2886,7 @@ var LibraryGL = { currentMatrix: 'm', // default is modelview tempMatrix: null, matricesModified: false, + useTextureMatrix: false, // Clientside attributes VERTEX: 0, @@ -2000,8 +2899,8 @@ var LibraryGL = { TEXTURE4: 7, TEXTURE5: 8, TEXTURE6: 9, - NUM_ATTRIBUTES: 10, - NUM_TEXTURES: 7, + NUM_ATTRIBUTES: 10, // Overwritten in init(). + MAX_TEXTURES: 7, // Overwritten in init(). totalEnabledClientAttributes: 0, enabledClientAttributes: [0, 0], @@ -2010,6 +2909,8 @@ var LibraryGL = { modifiedClientAttributes: false, clientActiveTexture: 0, clientColor: null, + usedTexUnitList: [], + fixedFunctionProgram: null, setClientAttribute: function(name, size, type, stride, pointer) { var attrib = this.clientAttributes[name]; @@ -2042,7 +2943,9 @@ var LibraryGL = { if (!this.rendererComponents[name]) { this.rendererComponents[name] = 1; #if ASSERTIONS - assert(!this.enabledClientAttributes[name]); // cannot get mixed up with this, for example we will disable this later + if (this.enabledClientAttributes[name]) { + console.log("Warning: glTexCoord used after EnableClientState for TEXTURE_COORD_ARRAY for TEXTURE0. Disabling TEXTURE_COORD_ARRAY..."); + } #endif this.enabledClientAttributes[name] = true; this.setClientAttribute(name, size, type, 0, this.rendererComponentPointer); @@ -2062,19 +2965,18 @@ var LibraryGL = { // return a renderer object given the liveClientAttributes // we maintain a cache of renderers, optimized to not generate garbage var attributes = GL.immediate.liveClientAttributes; - var cacheItem = GL.immediate.rendererCache; + var cacheMap = GL.immediate.rendererCache; var temp; + var keyView = cacheMap.getStaticKeyView().reset(); + + // By attrib state: for (var i = 0; i < attributes.length; i++) { var attribute = attributes[i]; - temp = cacheItem[attribute.name]; - cacheItem = temp ? temp : (cacheItem[attribute.name] = GL.immediate.rendererCacheItemTemplate.slice()); - temp = cacheItem[attribute.size]; - cacheItem = temp ? temp : (cacheItem[attribute.size] = GL.immediate.rendererCacheItemTemplate.slice()); - 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()); - } - var fogParam; + keyView.next(attribute.name).next(attribute.size).next(attribute.type); + } + + // By fog state: + var fogParam = 0; if (GLEmulation.fogEnabled) { switch (GLEmulation.fogMode) { case 0x0801: // GL_EXP2 @@ -2087,33 +2989,40 @@ var LibraryGL = { fogParam = 3; break; } - } else { - fogParam = 0; } - temp = cacheItem[fogParam]; - cacheItem = temp ? temp : (cacheItem[fogParam] = GL.immediate.rendererCacheItemTemplate.slice()); - if (GL.currProgram) { // Note the order here; this one is last, and optional. Note that we cannot ensure it is dense, sadly - temp = cacheItem[GL.currProgram]; - cacheItem = temp ? temp : (cacheItem[GL.currProgram] = GL.immediate.rendererCacheItemTemplate.slice()); + keyView.next(fogParam); + + // By cur program: + keyView.next(GL.currProgram); + if (!GL.currProgram) { + GL.immediate.TexEnvJIT.traverseState(keyView); } - if (!cacheItem.renderer) { + + // If we don't already have it, create it. + if (!keyView.get()) { #if GL_DEBUG Module.printErr('generating renderer for ' + JSON.stringify(attributes)); #endif - cacheItem.renderer = this.createRenderer(); + keyView.set(this.createRenderer()); } - return cacheItem.renderer; + return keyView.get(); }, createRenderer: function(renderer) { var useCurrProgram = !!GL.currProgram; 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; - hasTextures = true; + for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + var texAttribName = GL.immediate.TEXTURE0 + i; + if (!GL.immediate.enabledClientAttributes[texAttribName]) + continue; + + if (!useCurrProgram) { + assert(GL.immediate.TexEnvJIT.getTexUnitType(i) != 0, "GL_TEXTURE" + i + " coords are supplied, but that texture unit is disabled in the fixed-function pipeline."); } + + textureSizes[i] = GL.immediate.clientAttributes[texAttribName].size; + textureTypes[i] = GL.immediate.clientAttributes[texAttribName].type; + hasTextures = true; } var positionSize = GL.immediate.clientAttributes[GL.immediate.VERTEX].size; var positionType = GL.immediate.clientAttributes[GL.immediate.VERTEX].type; @@ -2129,6 +3038,13 @@ var LibraryGL = { } var ret = { init: function() { + // For fixed-function shader generation. + var uTexUnitPrefix = 'u_texUnit'; + var aTexCoordPrefix = 'a_texCoord'; + var vTexCoordPrefix = 'v_texCoord'; + var vPrimColor = 'v_color'; + var uTexMatrixPrefix = GL.immediate.useTextureMatrix ? 'u_textureMatrix' : null; + if (useCurrProgram) { if (GL.shaderInfos[GL.programShaders[GL.currProgram][0]].type == Module.ctx.VERTEX_SHADER) { this.vertexShader = GL.shaders[GL.programShaders[GL.currProgram][0]]; @@ -2138,13 +3054,12 @@ var LibraryGL = { this.fragmentShader = GL.shaders[GL.programShaders[GL.currProgram][0]]; } this.program = GL.programs[GL.currProgram]; + this.usedTexUnitList = []; } else { // IMPORTANT NOTE: If you parameterize the shader source based on any runtime values // in order to create the least expensive shader possible based on the features being // used, you should also update the code in the beginning of getRenderer to make sure // that you cache the renderer based on the said parameters. - this.vertexShader = Module.ctx.createShader(Module.ctx.VERTEX_SHADER); - var zero = positionSize == 2 ? '0, ' : ''; if (GLEmulation.fogEnabled) { switch (GLEmulation.fogMode) { case 0x0801: // GL_EXP2 @@ -2161,47 +3076,95 @@ var LibraryGL = { break; } } - Module.ctx.shaderSource(this.vertexShader, 'attribute vec' + positionSize + ' a_position; \n' + - 'attribute vec2 a_texCoord0; \n' + - (hasTextures ? 'varying vec2 v_texCoord; \n' : '') + - 'varying vec4 v_color; \n' + - (colorSize ? 'attribute vec4 a_color; \n': 'uniform vec4 u_color; \n') + - (GLEmulation.fogEnabled ? 'varying float v_fogFragCoord; \n' : '') + - 'uniform mat4 u_modelView; \n' + - 'uniform mat4 u_projection; \n' + - 'void main() \n' + - '{ \n' + - ' vec4 ecPosition = (u_modelView * vec4(a_position, ' + zero + '1.0)); \n' + // eye-coordinate position - ' gl_Position = u_projection * ecPosition; \n' + - (hasTextures ? 'v_texCoord = a_texCoord0; \n' : '') + - (colorSize ? 'v_color = a_color; \n' : 'v_color = u_color; \n') + - (GLEmulation.fogEnabled ? 'v_fogFragCoord = abs(ecPosition.z);\n' : '') + - '} \n'); + + GL.immediate.TexEnvJIT.setGLSLVars(uTexUnitPrefix, vTexCoordPrefix, vPrimColor, uTexMatrixPrefix); + var fsTexEnvPass = GL.immediate.TexEnvJIT.genAllPassLines('gl_FragColor', 2); + + var texUnitAttribList = ''; + var texUnitVaryingList = ''; + var texUnitUniformList = ''; + var vsTexCoordInits = ''; + this.usedTexUnitList = GL.immediate.TexEnvJIT.getUsedTexUnitList(); + for (var i = 0; i < this.usedTexUnitList.length; i++) { + var texUnit = this.usedTexUnitList[i]; + texUnitAttribList += 'attribute vec4 ' + aTexCoordPrefix + texUnit + ';\n'; + texUnitVaryingList += 'varying vec4 ' + vTexCoordPrefix + texUnit + ';\n'; + texUnitUniformList += 'uniform sampler2D ' + uTexUnitPrefix + texUnit + ';\n'; + vsTexCoordInits += ' ' + vTexCoordPrefix + texUnit + ' = ' + aTexCoordPrefix + texUnit + ';\n'; + + if (GL.immediate.useTextureMatrix) { + texUnitUniformList += 'uniform mat4 ' + uTexMatrixPrefix + texUnit + ';\n'; + } + } + + var vsFogVaryingInit = null; + if (GLEmulation.fogEnabled) { + vsFogVaryingInit = ' v_fogFragCoord = abs(ecPosition.z);\n'; + } + + var vsSource = [ + 'attribute vec4 a_position;', + 'attribute vec4 a_color;', + 'varying vec4 v_color;', + texUnitAttribList, + texUnitVaryingList, + (GLEmulation.fogEnabled ? 'varying float v_fogFragCoord;' : null), + 'uniform mat4 u_modelView;', + 'uniform mat4 u_projection;', + 'void main()', + '{', + ' vec4 ecPosition = u_modelView * a_position;', // eye-coordinate position + ' gl_Position = u_projection * ecPosition;', + ' v_color = a_color;', + vsTexCoordInits, + vsFogVaryingInit, + '}', + '' + ].join('\n').replace(/\n\n+/g, '\n'); + + this.vertexShader = Module.ctx.createShader(Module.ctx.VERTEX_SHADER); + Module.ctx.shaderSource(this.vertexShader, vsSource); Module.ctx.compileShader(this.vertexShader); + var fogHeaderIfNeeded = null; + if (GLEmulation.fogEnabled) { + fogHeaderIfNeeded = [ + '', + 'varying float v_fogFragCoord; ', + 'uniform vec4 u_fogColor; ', + 'uniform float u_fogEnd; ', + 'uniform float u_fogScale; ', + 'uniform float u_fogDensity; ', + 'float ffog(in float ecDistance) { ', + fogFormula, + ' fog = clamp(fog, 0.0, 1.0); ', + ' return fog; ', + '}', + '', + ].join("\n"); + } + + var fogPass = null; + if (GLEmulation.fogEnabled) { + fogPass = 'gl_FragColor = vec4(mix(u_fogColor.rgb, gl_FragColor.rgb, ffog(v_fogFragCoord)), gl_FragColor.a);\n'; + } + + var fsSource = [ + 'precision mediump float;', + texUnitVaryingList, + texUnitUniformList, + 'varying vec4 v_color;', + fogHeaderIfNeeded, + 'void main()', + '{', + fsTexEnvPass, + fogPass, + '}', + '' + ].join("\n").replace(/\n\n+/g, '\n'); + this.fragmentShader = Module.ctx.createShader(Module.ctx.FRAGMENT_SHADER); - Module.ctx.shaderSource(this.fragmentShader, 'precision mediump float; \n' + - 'varying vec2 v_texCoord; \n' + - 'uniform sampler2D u_texture; \n' + - 'varying vec4 v_color; \n' + - (GLEmulation.fogEnabled ? ( - 'varying float v_fogFragCoord; \n' + - 'uniform vec4 u_fogColor; \n' + - 'uniform float u_fogEnd; \n' + - 'uniform float u_fogScale; \n' + - 'uniform float u_fogDensity; \n' + - 'float ffog(in float ecDistance) { \n' + - fogFormula + - ' fog = clamp(fog, 0.0, 1.0); \n' + - ' return fog; \n' + - '} \n' - ) : '') + - 'void main() \n' + - '{ \n' + - (hasTextures ? 'gl_FragColor = v_color * texture2D( u_texture, v_texCoord );\n' : - 'gl_FragColor = v_color;\n') + - (GLEmulation.fogEnabled ? 'gl_FragColor = vec4(mix(u_fogColor.rgb, gl_FragColor.rgb, ffog(v_fogFragCoord)), gl_FragColor.a); \n' : '') + - '} \n'); + Module.ctx.shaderSource(this.fragmentShader, fsSource); Module.ctx.compileShader(this.fragmentShader); this.program = Module.ctx.createProgram(); @@ -2212,12 +3175,36 @@ var LibraryGL = { } this.positionLocation = Module.ctx.getAttribLocation(this.program, 'a_position'); + this.texCoordLocations = []; - for (var i = 0; i < textureSizes.length; i++) { - if (textureSizes[i]) { + + for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + if (!GL.immediate.enabledClientAttributes[GL.immediate.TEXTURE0 + i]) { + this.texCoordLocations[i] = -1; + continue; + } + + if (useCurrProgram) { this.texCoordLocations[i] = Module.ctx.getAttribLocation(this.program, 'a_texCoord' + i); + } else { + this.texCoordLocations[i] = Module.ctx.getAttribLocation(this.program, aTexCoordPrefix + i); + } + } + + if (!useCurrProgram) { + // Temporarily switch to the program so we can set our sampler uniforms early. + var prevBoundProg = Module.ctx.getParameter(Module.ctx.CURRENT_PROGRAM); + Module.ctx.useProgram(this.program); + { + for (var i = 0; i < this.usedTexUnitList.length; i++) { + var texUnitID = this.usedTexUnitList[i]; + var texSamplerLoc = Module.ctx.getUniformLocation(this.program, uTexUnitPrefix + texUnitID); + Module.ctx.uniform1i(texSamplerLoc, texUnitID); + } } + Module.ctx.useProgram(prevBoundProg); } + this.textureMatrixLocations = []; for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { this.textureMatrixLocations[i] = Module.ctx.getUniformLocation(this.program, 'u_textureMatrix' + i); @@ -2225,16 +3212,12 @@ var LibraryGL = { this.colorLocation = Module.ctx.getAttribLocation(this.program, 'a_color'); this.normalLocation = Module.ctx.getAttribLocation(this.program, 'a_normal'); - this.textureLocation = Module.ctx.getUniformLocation(this.program, 'u_texture'); // only for immediate mode with no shaders, so only one is enough this.modelViewLocation = Module.ctx.getUniformLocation(this.program, 'u_modelView'); this.projectionLocation = Module.ctx.getUniformLocation(this.program, 'u_projection'); - this.hasColorAttribLocation = Module.ctx.getUniformLocation(this.program, 'u_hasColorAttrib'); - this.colorUniformLocation = Module.ctx.getUniformLocation(this.program, 'u_color'); this.hasTextures = hasTextures; - this.hasColorAttrib = colorSize > 0 && this.colorLocation >= 0; - this.hasColorUniform = !!this.colorUniformLocation; this.hasNormal = normalSize > 0 && this.normalLocation >= 0; + this.hasColor = (this.colorLocation === 0) || this.colorLocation > 0; this.floatType = Module.ctx.FLOAT; // minor optimization @@ -2294,6 +3277,7 @@ var LibraryGL = { if (!GL.currProgram) { Module.ctx.useProgram(this.program); + GL.immediate.fixedFunctionProgram = this.program; } if (this.modelViewLocation) Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GL.immediate.matrix['m']); @@ -2305,11 +3289,21 @@ var LibraryGL = { GL.immediate.stride, 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, - GL.immediate.stride, clientAttributes[GL.immediate.TEXTURE0 + i].offset); - Module.ctx.enableVertexAttribArray(this.texCoordLocations[i]); + //for (var i = 0; i < this.usedTexUnitList.length; i++) { + // var texUnitID = this.usedTexUnitList[i]; + for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { + var texUnitID = i; + var attribLoc = this.texCoordLocations[texUnitID]; + if (attribLoc === undefined || attribLoc < 0) continue; + + if (texUnitID < textureSizes.length && textureSizes[texUnitID]) { + Module.ctx.vertexAttribPointer(attribLoc, textureSizes[texUnitID], textureTypes[texUnitID], false, + GL.immediate.stride, GL.immediate.clientAttributes[GL.immediate.TEXTURE0 + texUnitID].offset); + Module.ctx.enableVertexAttribArray(attribLoc); + } else { + // These two might be dangerous, but let's try them. + Module.ctx.vertexAttrib4f(attribLoc, 0, 0, 0, 1); + Module.ctx.disableVertexAttribArray(attribLoc); } } for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { @@ -2318,26 +3312,19 @@ var LibraryGL = { } } } - if (this.hasColorAttrib) { + if (colorSize) { Module.ctx.vertexAttribPointer(this.colorLocation, colorSize, colorType, true, GL.immediate.stride, clientAttributes[GL.immediate.COLOR].offset); Module.ctx.enableVertexAttribArray(this.colorLocation); - Module.ctx.uniform1i(this.hasColorAttribLocation, 1); - } else if (this.hasColorUniform) { - Module.ctx.uniform1i(this.hasColorAttribLocation, 0); - Module.ctx.uniform4fv(this.colorUniformLocation, GL.immediate.clientColor); + } else if (this.hasColor) { + Module.ctx.disableVertexAttribArray(this.colorLocation); + Module.ctx.vertexAttrib4fv(this.colorLocation, GL.immediate.clientColor); } if (this.hasNormal) { Module.ctx.vertexAttribPointer(this.normalLocation, normalSize, normalType, true, GL.immediate.stride, clientAttributes[GL.immediate.NORMAL].offset); Module.ctx.enableVertexAttribArray(this.normalLocation); } - if (!useCurrProgram) { // otherwise, the user program will set the sampler2D binding and uniform itself - var texture = Module.ctx.getParameter(Module.ctx.TEXTURE_BINDING_2D); - Module.ctx.activeTexture(Module.ctx.TEXTURE0); - Module.ctx.bindTexture(Module.ctx.TEXTURE_2D, texture); - Module.ctx.uniform1i(this.textureLocation, 0); - } if (this.hasFog) { if (this.fogColorLocation) Module.ctx.uniform4fv(this.fogColorLocation, GLEmulation.fogColor); if (this.fogEndLocation) Module.ctx.uniform1f(this.fogEndLocation, GLEmulation.fogEnd); @@ -2355,7 +3342,7 @@ var LibraryGL = { } } } - if (this.hasColorAttrib) { + if (this.hasColor) { Module.ctx.disableVertexAttribArray(this.colorLocation); } if (this.hasNormal) { @@ -2408,6 +3395,9 @@ var LibraryGL = { if (!GL.currElementArrayBuffer) { assert(type == Module.ctx.UNSIGNED_SHORT); // We can only emulate buffers of this kind, for now } +#if ASSERTIONS + console.log("DrawElements doesn't actually prepareClientAttributes properly."); +#endif GL.immediate.prepareClientAttributes(count, false); GL.immediate.mode = mode; if (!GL.currArrayBuffer) { @@ -2418,6 +3408,76 @@ var LibraryGL = { GL.immediate.flush(count, 0, indices); GL.immediate.mode = -1; }; + + // TexEnv stuff needs to be prepared early, so do it here. + // init() is too late for -O2, since it freezes the GL functions + // by that point. + GL.immediate.MapTreeLib = GL.immediate.spawnMapTreeLib(); + GL.immediate.spawnMapTreeLib = null; + + GL.immediate.TexEnvJIT = GL.immediate.spawnTexEnvJIT(); + GL.immediate.spawnTexEnvJIT = null; + + GL.immediate.setupHooks(); + }, + + setupHooks: function() { + if (!GLEmulation.hasRunInit) { + GLEmulation.init(); + } + + var glActiveTexture = _glActiveTexture; + _glActiveTexture = function(texture) { + GL.immediate.TexEnvJIT.hook_activeTexture(texture); + glActiveTexture(texture); + }; + + var glEnable = _glEnable; + _glEnable = function(cap) { + GL.immediate.TexEnvJIT.hook_enable(cap); + glEnable(cap); + }; + var glDisable = _glDisable; + _glDisable = function(cap) { + GL.immediate.TexEnvJIT.hook_disable(cap); + glDisable(cap); + }; + + var glTexEnvf = (typeof(_glTexEnvf) != 'undefined') ? _glTexEnvf : function(){}; + _glTexEnvf = function(target, pname, param) { + GL.immediate.TexEnvJIT.hook_texEnvf(target, pname, param); + // Don't call old func, since we are the implementor. + //glTexEnvf(target, pname, param); + }; + var glTexEnvi = (typeof(_glTexEnvi) != 'undefined') ? _glTexEnvi : function(){}; + _glTexEnvi = function(target, pname, param) { + GL.immediate.TexEnvJIT.hook_texEnvi(target, pname, param); + // Don't call old func, since we are the implementor. + //glTexEnvi(target, pname, param); + }; + var glTexEnvfv = (typeof(_glTexEnvfv) != 'undefined') ? _glTexEnvfv : function(){}; + _glTexEnvfv = function(target, pname, param) { + GL.immediate.TexEnvJIT.hook_texEnvfv(target, pname, param); + // Don't call old func, since we are the implementor. + //glTexEnvfv(target, pname, param); + }; + + var glGetIntegerv = _glGetIntegerv; + _glGetIntegerv = function(pname, params) { + switch (pname) { + case 0x8B8D: { // GL_CURRENT_PROGRAM + // Just query directly so we're working with WebGL objects. + var cur = Module.ctx.getParameter(Module.ctx.CURRENT_PROGRAM); + if (cur == GL.immediate.fixedFunctionProgram) { + // Pretend we're not using a program. + {{{ makeSetValue('params', '0', '0', 'i32') }}}; + return; + } + break; + } + } + glGetIntegerv(pname, params); + }; }, // Main functions @@ -2428,6 +3488,15 @@ var LibraryGL = { if (!Module.useWebGL) return; // a 2D canvas may be currently used TODO: make sure we are actually called in that case + this.TexEnvJIT.init(Module.ctx); + + GL.immediate.MAX_TEXTURES = Module.ctx.getParameter(Module.ctx.MAX_TEXTURE_IMAGE_UNITS); + GL.immediate.NUM_ATTRIBUTES = GL.immediate.TEXTURE0 + GL.immediate.MAX_TEXTURES; + GL.immediate.clientAttributes = []; + for (var i = 0; i < GL.immediate.NUM_ATTRIBUTES; i++) { + GL.immediate.clientAttributes.push({}); + } + this.matrixStack['m'] = []; this.matrixStack['p'] = []; for (var i = 0; i < GL.immediate.MAX_TEXTURES; i++) { @@ -2445,7 +3514,7 @@ var LibraryGL = { } // Renderer cache - this.rendererCache = this.rendererCacheItemTemplate.slice(); + this.rendererCache = this.MapTreeLib.create(); // Buffers for data this.tempData = new Float32Array(GL.MAX_TEMP_BUFFER_SIZE >> 2); @@ -2486,6 +3555,7 @@ var LibraryGL = { if (stride != 0 && stride != attribute.stride) multiStrides = true; if (attribute.stride) stride = attribute.stride; } + if (multiStrides) stride = 0; // we will need to restride var bytes = 0; // total size in bytes if (!stride && !beginEnd) { @@ -2564,8 +3634,8 @@ var LibraryGL = { var renderer = this.getRenderer(); // Generate index data in a format suitable for GLES 2.0/WebGL - var numVertexes = 4 * this.vertexCounter / GL.immediate.stride; // XXX assuming float - assert(numVertexes % 1 == 0); + var numVertexes = 4 * this.vertexCounter / GL.immediate.stride; + assert(numVertexes % 1 == 0, "`numVertexes` must be an integer."); var emulatedElementArrayBuffer = false; var numIndexes = 0; @@ -2629,6 +3699,16 @@ var LibraryGL = { glBegin__deps: ['$GLImmediateSetup'], glBegin: function(mode) { + // Push the old state: + GL.immediate.enabledClientAttributes_preBegin = GL.immediate.enabledClientAttributes; + GL.immediate.enabledClientAttributes = []; + + GL.immediate.clientAttributes_preBegin = GL.immediate.clientAttributes; + GL.immediate.clientAttributes = [] + for (var i = 0; i < GL.immediate.clientAttributes_preBegin.length; i++) { + GL.immediate.clientAttributes.push({}); + } + GL.immediate.mode = mode; GL.immediate.vertexCounter = 0; var components = GL.immediate.rendererComponents = []; @@ -2646,6 +3726,12 @@ var LibraryGL = { GL.immediate.flush(); GL.immediate.disableBeginEndClientAttributes(); GL.immediate.mode = -1; + + // Pop the old state: + GL.immediate.enabledClientAttributes = GL.immediate.enabledClientAttributes_preBegin; + GL.immediate.clientAttributes = GL.immediate.clientAttributes_preBegin; + + GL.immediate.modifiedClientAttributes = true; }, glVertex3f: function(x, y, z) { @@ -2670,7 +3756,7 @@ var LibraryGL = { glVertex2fv: function(p) { _glVertex3f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}}, 0); }, - + glVertex3i: 'glVertex3f', glVertex2i: 'glVertex3f', @@ -2879,11 +3965,11 @@ var LibraryGL = { }, // Vertex array object (VAO) support. TODO: when the WebGL extension is popular, use that and remove this code and GL.vaos - glGenVertexArrays__deps: ['$GLEMulation'], + glGenVertexArrays__deps: ['$GLEmulation'], glGenVertexArrays__sig: 'vii', glGenVertexArrays: function(n, vaos) { for (var i = 0; i < n; i++) { - var id = GL.getNewId(GLEmulation.vaos); + var id = GL.getNewId(GLEmulation.vaos); GLEmulation.vaos[id] = { id: id, arrayBuffer: 0, @@ -2944,6 +4030,7 @@ var LibraryGL = { } else if (mode == 0x1701 /* GL_PROJECTION */) { GL.immediate.currentMatrix = 'p'; } else if (mode == 0x1702) { // GL_TEXTURE + GL.immediate.useTextureMatrix = true; GL.immediate.currentMatrix = 't' + GL.immediate.clientActiveTexture; } else { throw "Wrong mode " + mode + " passed to glMatrixMode"; @@ -3113,7 +4200,7 @@ var LibraryGL = { return 1 /* GL_TRUE */; }, - + gluOrtho2D: function(left, right, bottom, top) { _glOrtho(left, right, bottom, top, -1, 1); }, @@ -3280,9 +4367,10 @@ var LibraryGL = { glGenVertexArraysOES: 'glGenVertexArrays', glDeleteVertexArraysOES: 'glDeleteVertexArrays', glBindVertexArrayOES: 'glBindVertexArray', - glFramebufferTexture2DOES: 'glFramebufferTexture2D' + glFramebufferTexture2DOES: 'glFramebufferTexture2D', }; + // Simple pass-through functions. Starred ones have return values. [X] ones have X in the C name but not in the JS name [[0, 'getError* finish flush'], [1, 'clearDepth clearDepth[f] depthFunc enable disable frontFace cullFace clear lineWidth clearStencil depthMask stencilMask checkFramebufferStatus* generateMipmap activeTexture blendEquation sampleCoverage isEnabled*'], diff --git a/src/library_sdl.js b/src/library_sdl.js index d31c37f5..4f871f9d 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -694,6 +694,11 @@ var LibrarySDL = { Module['canvas'].addEventListener(event, SDL.receiveEvent, true); }); Browser.setCanvasSize(width, height, true); + // Free the old surface first. + if (SDL.screen) { + SDL.freeSurface(SDL.screen); + SDL.screen = null; + } SDL.screen = SDL.makeSurface(width, height, flags, true, 'screen'); if (!SDL.addedResizeListener) { SDL.addedResizeListener = true; diff --git a/src/parseTools.js b/src/parseTools.js index 45046558..3949491e 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -2038,12 +2038,20 @@ function processMathop(item) { } var bitsBefore = parseInt((item.params[0] ? item.params[0].type : item.type).substr(1)); // remove i to leave the number of bits left after this var bitsLeft = parseInt(((item.params[1] && item.params[1].ident) ? item.params[1].ident : item.type).substr(1)); // remove i to leave the number of bits left after this operation + var rawBits = getBits(item.type); + assert(rawBits <= 64); function integerizeBignum(value) { return makeInlineCalculation('VALUE-VALUE%1', value, 'tempBigIntI'); } - if ((type == 'i64' || paramTypes[0] == 'i64' || paramTypes[1] == 'i64' || idents[1] == '(i64)') && USE_TYPED_ARRAYS == 2) { + if ((type == 'i64' || paramTypes[0] == 'i64' || paramTypes[1] == 'i64' || idents[1] == '(i64)' || rawBits > 32) && USE_TYPED_ARRAYS == 2) { + // this code assumes i64 for the most part + if (ASSERTIONS && rawBits > 1 && rawBits < 64) { + warnOnce('processMathop processing illegal non-i64 value'); + if (VERBOSE) printErr([op, item.type, rawBits, type, paramTypes, idents]); + } + var warnI64_1 = function() { warnOnce('Arithmetic on 64-bit integers in mode 1 is rounded and flaky, like mode 0!'); }; diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp index 61daed79..8c72b0a6 100644 --- a/src/relooper/Relooper.cpp +++ b/src/relooper/Relooper.cpp @@ -104,9 +104,6 @@ Block::Block(const char *CodeInit) : Parent(NULL), Id(Block::IdCounter++), Defau Block::~Block() { if (Code) free((void*)Code); - for (BlockBranchMap::iterator iter = ProcessedBranchesIn.begin(); iter != ProcessedBranchesIn.end(); iter++) { - delete iter->second; - } for (BlockBranchMap::iterator iter = ProcessedBranchesOut.begin(); iter != ProcessedBranchesOut.end(); iter++) { delete iter->second; } @@ -139,10 +136,6 @@ void Block::Render(bool InLoop) { bool SetLabel = true; // in some cases it is clear we can avoid setting label, see later - if (ProcessedBranchesOut.size() == 1 && ProcessedBranchesOut.begin()->second->Type == Branch::Direct) { - SetLabel = false; - } - // A setting of the label variable (label = x) is necessary if it can // cause an impact. The main case is where we set label to x, then elsewhere // we check if label is equal to that value, i.e., that label is an entry @@ -379,22 +372,47 @@ void Relooper::Calculate(Block *Entry) { Block *Curr = *iter; TotalCodeSize += strlen(Curr->Code); } - + BlockSet Splits; + BlockSet Removed; + //DebugDump(Live, "before"); for (BlockSet::iterator iter = Live.begin(); iter != Live.end(); iter++) { Block *Original = *iter; - if (Original->BranchesIn.size() <= 1 || Original->BranchesOut.size() > 0) continue; + if (Original->BranchesIn.size() <= 1 || Original->BranchesOut.size() > 0) continue; // only dead ends, for now + if (Original->BranchesOut.find(Original) != Original->BranchesOut.end()) continue; // cannot split a looping node if (strlen(Original->Code)*(Original->BranchesIn.size()-1) > TotalCodeSize/5) continue; // if splitting increases raw code size by a significant amount, abort // Split the node (for simplicity, we replace all the blocks, even though we could have reused the original) - for (BlockBranchMap::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) { - Block *Prior = iter->first; + PrintDebug("Splitting block %d\n", Original->Id); + for (BlockSet::iterator iter = Original->BranchesIn.begin(); iter != Original->BranchesIn.end(); iter++) { + Block *Prior = *iter; Block *Split = new Block(Original->Code); - Split->BranchesIn[Prior] = new Branch(NULL); - Prior->BranchesOut[Split] = new Branch(Prior->BranchesOut[Original]->Condition, Prior->BranchesOut[Original]->Code); + Parent->Blocks.push_back(Split); + PrintDebug(" to %d\n", Split->Id); + Split->BranchesIn.insert(Prior); + Branch *Details = Prior->BranchesOut[Original]; + Prior->BranchesOut[Split] = new Branch(Details->Condition, Details->Code); Prior->BranchesOut.erase(Original); - Parent->AddBlock(Split); - Live.insert(Split); + for (BlockBranchMap::iterator iter = Original->BranchesOut.begin(); iter != Original->BranchesOut.end(); iter++) { + Block *Post = iter->first; + Branch *Details = iter->second; + Split->BranchesOut[Post] = new Branch(Details->Condition, Details->Code); + Post->BranchesIn.insert(Split); + } + Splits.insert(Split); + Removed.insert(Original); + } + for (BlockBranchMap::iterator iter = Original->BranchesOut.begin(); iter != Original->BranchesOut.end(); iter++) { + Block *Post = iter->first; + Post->BranchesIn.erase(Original); } + //DebugDump(Live, "mid"); + } + for (BlockSet::iterator iter = Splits.begin(); iter != Splits.end(); iter++) { + Live.insert(*iter); + } + for (BlockSet::iterator iter = Removed.begin(); iter != Removed.end(); iter++) { + Live.erase(*iter); } + //DebugDump(Live, "after"); } }; PreOptimizer Pre(this); @@ -405,7 +423,7 @@ void Relooper::Calculate(Block *Entry) { Block *Curr = Blocks[i]; if (Pre.Live.find(Curr) == Pre.Live.end()) continue; for (BlockBranchMap::iterator iter = Curr->BranchesOut.begin(); iter != Curr->BranchesOut.end(); iter++) { - iter->first->BranchesIn[Curr] = new Branch(NULL); + iter->first->BranchesIn.insert(Curr); } } @@ -435,22 +453,21 @@ void Relooper::Calculate(Block *Entry) { void Solipsize(Block *Target, Branch::FlowType Type, Shape *Ancestor, BlockSet &From) { PrintDebug("Solipsizing branches into %d\n", Target->Id); DebugDump(From, " relevant to solipsize: "); - for (BlockBranchMap::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) { - Block *Prior = iter->first; + for (BlockSet::iterator iter = Target->BranchesIn.begin(); iter != Target->BranchesIn.end();) { + Block *Prior = *iter; if (From.find(Prior) == From.end()) { iter++; continue; } - Branch *TargetIn = iter->second; Branch *PriorOut = Prior->BranchesOut[Target]; - PriorOut->Ancestor = Ancestor; // Do we need this info - PriorOut->Type = Type; // on TargetIn too? + PriorOut->Ancestor = Ancestor; + PriorOut->Type = Type; if (MultipleShape *Multiple = Shape::IsMultiple(Ancestor)) { Multiple->NeedLoop++; // We are breaking out of this Multiple, so need a loop } iter++; // carefully increment iter before erasing Target->BranchesIn.erase(Prior); - Target->ProcessedBranchesIn[Prior] = TargetIn; + Target->ProcessedBranchesIn.insert(Prior); Prior->BranchesOut.erase(Target); Prior->ProcessedBranchesOut[Target] = PriorOut; PrintDebug(" eliminated branch from %d\n", Prior->Id); @@ -488,8 +505,8 @@ void Relooper::Calculate(Block *Entry) { InnerBlocks.insert(Curr); Blocks.erase(Curr); // Add the elements prior to it - for (BlockBranchMap::iterator iter = Curr->BranchesIn.begin(); iter != Curr->BranchesIn.end(); iter++) { - Queue.insert(iter->first); + for (BlockSet::iterator iter = Curr->BranchesIn.begin(); iter != Curr->BranchesIn.end(); iter++) { + Queue.insert(*iter); } } } @@ -620,8 +637,8 @@ void Relooper::Calculate(Block *Entry) { BlockList ToInvalidate; for (BlockSet::iterator iter = CurrGroup.begin(); iter != CurrGroup.end(); iter++) { Block *Child = *iter; - for (BlockBranchMap::iterator iter = Child->BranchesIn.begin(); iter != Child->BranchesIn.end(); iter++) { - Block *Parent = iter->first; + for (BlockSet::iterator iter = Child->BranchesIn.begin(); iter != Child->BranchesIn.end(); iter++) { + Block *Parent = *iter; if (Helper.Ownership[Parent] != Helper.Ownership[Child]) { ToInvalidate.push_back(Child); } @@ -751,8 +768,8 @@ void Relooper::Calculate(Block *Entry) { Block *Entry = iter->first; BlockSet &Group = iter->second; BlockBlockSetMap::iterator curr = iter++; // iterate carefully, we may delete - for (BlockBranchMap::iterator iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) { - Block *Origin = iterBranch->first; + for (BlockSet::iterator iterBranch = Entry->BranchesIn.begin(); iterBranch != Entry->BranchesIn.end(); iterBranch++) { + Block *Origin = *iterBranch; if (Group.find(Origin) == Group.end()) { // Reached from outside the group, so we cannot handle this PrintDebug("Cannot handle group with entry %d because of incoming branch from %d\n", Entry->Id, Origin->Id); @@ -821,13 +838,11 @@ void Relooper::Calculate(Block *Entry) { // Main BlockSet AllBlocks; - for (int i = 0; i < Blocks.size(); i++) { - AllBlocks.insert(Blocks[i]); + for (BlockSet::iterator iter = Pre.Live.begin(); iter != Pre.Live.end(); iter++) { + Block *Curr = *iter; + AllBlocks.insert(Curr); #if DEBUG - PrintDebug("Adding block %d (%s)\n", Blocks[i]->Id, Blocks[i]->Code); - for (BlockBranchMap::iterator iter = Blocks[i]->BranchesOut.begin(); iter != Blocks[i]->BranchesOut.end(); iter++) { - PrintDebug(" with branch out to %d\n", iter->first->Id); - } + PrintDebug("Adding block %d (%s)\n", Curr->Id, Curr->Code); #endif } @@ -874,10 +889,26 @@ void Relooper::Calculate(Block *Entry) { func(Loop->Next); \ } + // Find the blocks that natural control flow can get us directly to, or through a multiple that we ignore + void FollowNaturalFlow(Shape *S, BlockSet &Out) { + SHAPE_SWITCH(S, { + Out.insert(Simple->Inner); + }, { + for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { + FollowNaturalFlow(iter->second, Out); + } + FollowNaturalFlow(Multiple->Next, Out); + }, { + FollowNaturalFlow(Loop->Inner, Out); + }); + } + // Remove unneeded breaks and continues. // A flow operation is trivially unneeded if the shape we naturally get to by normal code // execution is the same as the flow forces us to. void RemoveUnneededFlows(Shape *Root, Shape *Natural=NULL) { + BlockSet NaturalBlocks; + FollowNaturalFlow(Natural, NaturalBlocks); Shape *Next = Root; while (Next) { Root = Next; @@ -892,7 +923,7 @@ void Relooper::Calculate(Block *Entry) { for (BlockBranchMap::iterator iter = Simple->Inner->ProcessedBranchesOut.begin(); iter != Simple->Inner->ProcessedBranchesOut.end(); iter++) { Block *Target = iter->first; Branch *Details = iter->second; - if (Details->Type != Branch::Direct && Target->Parent == Natural) { + if (Details->Type != Branch::Direct && NaturalBlocks.find(Target) != NaturalBlocks.end()) { // note: cannot handle split blocks Details->Type = Branch::Direct; if (MultipleShape *Multiple = Shape::IsMultiple(Details->Ancestor)) { Multiple->NeedLoop--; @@ -1007,12 +1038,32 @@ void Relooper::SetAsmJSMode(int On) { #if DEBUG // Debugging -void DebugDump(BlockSet &Blocks, const char *prefix) { +void Debugging::Dump(BlockSet &Blocks, const char *prefix) { if (prefix) printf("%s ", prefix); for (BlockSet::iterator iter = Blocks.begin(); iter != Blocks.end(); iter++) { - printf("%d ", (*iter)->Id); + Block *Curr = *iter; + printf("%d:\n", Curr->Id); + for (BlockBranchMap::iterator iter2 = Curr->BranchesOut.begin(); iter2 != Curr->BranchesOut.end(); iter2++) { + Block *Other = iter2->first; + printf(" -> %d\n", Other->Id); + assert(Other->BranchesIn.find(Curr) != Other->BranchesIn.end()); + } } - printf("\n"); +} + +void Debugging::Dump(Shape *S, const char *prefix) { + if (prefix) printf("%s ", prefix); + printf(" %d ", S->Id); + SHAPE_SWITCH(S, { + printf("<< Simple with block %d\n", Simple->Inner->Id); + }, { + printf("<< Multiple\n"); + for (BlockShapeMap::iterator iter = Multiple->InnerMap.begin(); iter != Multiple->InnerMap.end(); iter++) { + printf(" with entry %d\n", iter->first->Id); + } + }, { + printf("<< Loop\n"); + }); } static void PrintDebug(const char *Format, ...) { diff --git a/src/relooper/Relooper.h b/src/relooper/Relooper.h index eac03738..34b6db08 100644 --- a/src/relooper/Relooper.h +++ b/src/relooper/Relooper.h @@ -41,6 +41,7 @@ struct Branch { void Render(Block *Target, bool SetLabel); }; +typedef std::set<Block*> BlockSet; typedef std::map<Block*, Branch*> BlockBranchMap; // Represents a basic block of code - some instructions that end with a @@ -52,9 +53,9 @@ struct Block { // processed branches. // Blocks own the Branch objects they use, and destroy them when done. BlockBranchMap BranchesOut; - BlockBranchMap BranchesIn; // TODO: make this just a list of Incoming, without branch info - should be just on BranchesOut + BlockSet BranchesIn; BlockBranchMap ProcessedBranchesOut; - BlockBranchMap ProcessedBranchesIn; + BlockSet ProcessedBranchesIn; Shape *Parent; // The shape we are directly inside int Id; // A unique identifier const char *Code; // The string representation of the code in this block. Owning pointer (we copy the input) @@ -205,12 +206,12 @@ struct Relooper { static void SetAsmJSMode(int On); }; -typedef std::set<Block*> BlockSet; typedef std::map<Block*, BlockSet> BlockBlockSetMap; #if DEBUG struct Debugging { static void Dump(BlockSet &Blocks, const char *prefix=NULL); + static void Dump(Shape *S, const char *prefix=NULL); }; #endif diff --git a/src/relooper/fuzzer.py b/src/relooper/fuzzer.py index 96929028..5f6bae3d 100644 --- a/src/relooper/fuzzer.py +++ b/src/relooper/fuzzer.py @@ -98,14 +98,14 @@ int main() { open('fuzz.slow.js', 'w').write(slow) open('fuzz.cpp', 'w').write(fast) print '_' - slow_out = subprocess.Popen(['/home/alon/Dev/odinmonkey/js/src/fast/js', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0] + slow_out = subprocess.Popen(['mozjs', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0] print '.' subprocess.call(['g++', 'fuzz.cpp', 'Relooper.o', '-o', 'fuzz', '-g']) print '*' subprocess.call(['./fuzz'], stdout=open('fuzz.fast.js', 'w')) print '-' - fast_out = subprocess.Popen(['/home/alon/Dev/odinmonkey/js/src/fast/js', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0] + fast_out = subprocess.Popen(['mozjs', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0] print if slow_out != fast_out: diff --git a/src/relooper/test.cpp b/src/relooper/test.cpp index 4275941b..7da990b5 100644 --- a/src/relooper/test.cpp +++ b/src/relooper/test.cpp @@ -190,5 +190,46 @@ int main() { puts(buffer); } + + if (1) { + Relooper::SetOutputBuffer(buffer, sizeof(buffer)); + + printf("\n\n-- if (expensive || expensive2) X else Y; Z --\n\n"); + + Block *b_a = new Block("// block A\n"); + Block *b_b = new Block("// block B\n"); + Block *b_c = new Block("// block C;\n"); + Block *b_d = new Block("// block D\n"); + Block *b_e = new Block("// block E\n"); + Block *b_f = new Block("// block F\n"); + + b_a->AddBranchTo(b_c, "expensive()"); + b_a->AddBranchTo(b_b, NULL); + + b_b->AddBranchTo(b_c, "expensive2()"); + b_b->AddBranchTo(b_d, NULL); + + b_c->AddBranchTo(b_e, NULL); + + b_d->AddBranchTo(b_e, NULL); + + b_e->AddBranchTo(b_f, NULL); + + b_f->AddBranchTo(b_e, NULL); + + Relooper r; + r.AddBlock(b_a); + r.AddBlock(b_b); + r.AddBlock(b_c); + r.AddBlock(b_d); + r.AddBlock(b_e); + r.AddBlock(b_f); + + r.Calculate(b_a); + printf("\n\n"); + r.Render(); + + puts(buffer); + } } diff --git a/src/relooper/test.txt b/src/relooper/test.txt index 12d0ef39..d657c6af 100644 --- a/src/relooper/test.txt +++ b/src/relooper/test.txt @@ -109,3 +109,30 @@ while(1) { // block D } + + +-- if (expensive || expensive2) X else Y; Z -- + + + +// block A +do { + if (expensive()) { + label = 33; + } else { + // block B + if (expensive2()) { + label = 33; + break; + } + // block D + } +} while(0); +if (label == 33) { + // block C; +} +while(1) { + // block E + // block F +} + diff --git a/src/relooper/test4.txt b/src/relooper/test4.txt index f0bfb972..3427ff18 100644 --- a/src/relooper/test4.txt +++ b/src/relooper/test4.txt @@ -7,7 +7,6 @@ do { break; } //21 - break; } else { label = 4; } diff --git a/src/relooper/test_debug.txt b/src/relooper/test_debug.txt index 1c7d0508..d18ed875 100644 --- a/src/relooper/test_debug.txt +++ b/src/relooper/test_debug.txt @@ -28,56 +28,88 @@ int main() { return 0; } // Adding block 1 (ep) -// with branch out to 2 -// with branch out to 4 // Adding block 2 (LBB1) -// with branch out to 3 -// with branch out to 4 // Adding block 3 (LBB2) -// with branch out to 4 // Adding block 4 (LBB3) // Process() called // Process() running - blocks : 1 2 3 4 - entries: 1 + blocks : 1: + -> 2 + -> 4 +2: + -> 3 + -> 4 +3: + -> 4 +4: + entries: 1: + -> 2 + -> 4 // creating simple block with block #1 // Solipsizing branches into 2 - relevant to solipsize: 1 + relevant to solipsize: 1: + -> 2 + -> 4 // eliminated branch from 1 // Solipsizing branches into 4 - relevant to solipsize: 1 + relevant to solipsize: 1: + -> 4 // eliminated branch from 1 // Process() running - blocks : 2 3 4 - entries: 2 4 + blocks : 2: + -> 3 + -> 4 +3: + -> 4 +4: + entries: 2: + -> 3 + -> 4 +4: // Investigated independent groups: - group: 2 3 + group: 2: + -> 3 + -> 4 +3: + -> 4 // Independent groups: 1 // Handleable independent groups: 1 // creating multiple block with 1 inner groups // multiple group with entry 2: - 2 3 + 2: + -> 3 + -> 4 +3: + -> 4 // Solipsizing branches into 4 - relevant to solipsize: 2 3 + relevant to solipsize: 2: + -> 3 + -> 4 +3: + -> 4 // eliminated branch from 2 // eliminated branch from 3 // Process() called // Process() running - blocks : 2 3 - entries: 2 + blocks : 2: + -> 3 +3: + entries: 2: + -> 3 // creating simple block with block #2 // Solipsizing branches into 3 - relevant to solipsize: 2 + relevant to solipsize: 2: + -> 3 // eliminated branch from 2 // Process() running - blocks : 3 - entries: 3 + blocks : 3: + entries: 3: // creating simple block with block #3 // Process() returning - remaining blocks after multiple: 4 + remaining blocks after multiple: 4: // Process() running - blocks : 4 - entries: 4 + blocks : 4: + entries: 4: // creating simple block with block #4 // Process() returning // === Optimizing shapes === diff --git a/src/relooper/test_fuzz1.txt b/src/relooper/test_fuzz1.txt index 5122257e..b278e240 100644 --- a/src/relooper/test_fuzz1.txt +++ b/src/relooper/test_fuzz1.txt @@ -3,13 +3,10 @@ print('entry'); var label; var state; var decisions = [4, 1, 7, 2, 6, 6, 8]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] } print(5); state = check(); print(6); state = check(); -do { - if (state == 7) { - print(7); state = check(); - label = 3; - break; - } -} while(0); +if (state == 7) { + print(7); state = check(); + label = 3; +} L5: while(1) { if (label == 3) { label = 0; diff --git a/src/relooper/test_fuzz5.txt b/src/relooper/test_fuzz5.txt index 9548205c..29b2dba4 100644 --- a/src/relooper/test_fuzz5.txt +++ b/src/relooper/test_fuzz5.txt @@ -3,22 +3,18 @@ print('entry'); var label; var state; var decisions = [133, 98, 134, 143, 162, 187, 130, 87, 91, 49, 102, 47, 9, 132, 179, 176, 157, 25, 64, 161, 57, 107, 16, 167, 185, 45, 191, 180, 23, 131]; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] } L1: while(1) { print(7); state = check(); - do { - if (state % 3 == 1) { - label = 3; - } else if (state % 3 == 0) { - print(8); state = check(); - if (state % 2 == 0) { - label = 5; - break; - } else { - label = 7; - break; - } + if (state % 3 == 1) { + label = 3; + } else if (state % 3 == 0) { + print(8); state = check(); + if (state % 2 == 0) { + label = 5; } else { - break L1; + label = 7; } - } while(0); + } else { + break; + } while(1) { if (label == 3) { label = 0; diff --git a/src/relooper/test_fuzz6.txt b/src/relooper/test_fuzz6.txt index bd45e8fd..d5a5ab7b 100644 --- a/src/relooper/test_fuzz6.txt +++ b/src/relooper/test_fuzz6.txt @@ -82,7 +82,6 @@ while(1) { print(56); state = check();// .................................................................................................................................................................................................................... print(34); state = check();// .......................................................................................................................................... label = 74; - continue; } print(62); state = check();// ....................................................................................... } diff --git a/src/relooper/testit.sh b/src/relooper/testit.sh index 61e1a2fb..88db35fb 100755 --- a/src/relooper/testit.sh +++ b/src/relooper/testit.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash echo "test" ./test &> test.out diff --git a/src/relooper/updateit.sh b/src/relooper/updateit.sh index 8c434753..da9fa9aa 100755 --- a/src/relooper/updateit.sh +++ b/src/relooper/updateit.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash ./test &> test.txt ./test2 &> test2.txt ./test3 &> test3.txt diff --git a/system/include/libcxx/exception b/system/include/libcxx/exception index 4b5770b7..102b10d6 100644 --- a/system/include/libcxx/exception +++ b/system/include/libcxx/exception @@ -91,8 +91,8 @@ class _LIBCPP_EXCEPTION_ABI exception { public: _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {} - virtual ~exception() _NOEXCEPT {}; // XXX EMSCRIPTEN inline in destructor - virtual const char* what() const _NOEXCEPT; + virtual ~exception() _NOEXCEPT {} // XXX EMSCRIPTEN - implement in header + virtual const char* what() const _NOEXCEPT { return "std::exception"; } // XXX EMSCRIPTEN - implement in header }; class _LIBCPP_EXCEPTION_ABI bad_exception diff --git a/tests/aniso.c b/tests/aniso.c index e02c20ac..1126265e 100644 --- a/tests/aniso.c +++ b/tests/aniso.c @@ -64,7 +64,7 @@ int main(int argc, char *argv[]) const char *exts = (const char *)glGetString(GL_EXTENSIONS); assert(hasext(exts, "GL_EXT_texture_filter_anisotropic")); - + GLint aniso; glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso); printf("Max anisotropy: %d (using that)\n", aniso); @@ -73,10 +73,8 @@ int main(int argc, char *argv[]) // 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 600, 600 ); @@ -155,7 +153,7 @@ int main(int argc, char *argv[]) // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to int w = 10; int n = 15; @@ -200,7 +198,7 @@ int main(int argc, char *argv[]) } */ SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(2000); @@ -208,8 +206,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/cases/fp80.ll b/tests/cases/fp80_ta2.ll index 7fc0db4a..7fc0db4a 100644 --- a/tests/cases/fp80.ll +++ b/tests/cases/fp80_ta2.ll diff --git a/tests/cases/muli33_ta2.ll b/tests/cases/muli33_ta2.ll new file mode 100644 index 00000000..b33b04f7 --- /dev/null +++ b/tests/cases/muli33_ta2.ll @@ -0,0 +1,114 @@ +; ModuleID = '/tmp/tmpt0JpDh/a.out.bc' +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" + +@.str = private unnamed_addr constant [7 x i8] c"20\0A91\0A\00", align 1 +@.str1 = private unnamed_addr constant [6 x i8] c"%u %u\00", align 1 +@.str2 = private unnamed_addr constant [10 x i8] c"res = %u\0A\00", align 1 + +define i32 @main() nounwind { + %j = alloca i32, align 4 + %k4 = alloca i32, align 4 + %t = alloca [100 x [100 x i32]], align 4 + store i32 20, i32* %j, align 4 + store i32 91, i32* %k4, align 4 + br label %.lr.ph.i + +.lr.ph.i: ; preds = %.lr.ph.i, %0 + %j.07.i = phi i32 [ %7, %.lr.ph.i ], [ 0, %0 ] + %1 = and i32 %j.07.i, 1 + %2 = icmp eq i32 %1, 0 + %3 = sub i32 0, %j.07.i + %.p.i = select i1 %2, i32 %j.07.i, i32 %3 + %4 = add i32 %.p.i, 8 + %5 = urem i32 %4, 101 + %6 = getelementptr inbounds [100 x [100 x i32]]* %t, i32 0, i32 0, i32 %j.07.i + store i32 %5, i32* %6, align 4 + %7 = add i32 %j.07.i, 1 + %8 = icmp ult i32 %7, 10000 + br i1 %8, label %.lr.ph.i, label %init.exit + +init.exit: ; preds = %.lr.ph.i + %9 = call i32 (i8*, i8*, ...)* @sscanf(i8* getelementptr inbounds ([7 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([6 x i8]* @.str1, i32 0, i32 0), i32* %j, i32* %k4) nounwind + store i32 53, i32* %j, align 4 + br label %.preheader + +.preheader: ; preds = %29, %init.exit + %indvars.iv23 = phi i32 [ -29, %init.exit ], [ %indvars.iv.next24, %29 ] + %indvars.iv21 = phi i32 [ -28, %init.exit ], [ %indvars.iv.next22, %29 ] + %indvars.iv19 = phi i32 [ -27, %init.exit ], [ %indvars.iv.next20, %29 ] + %indvars.iv17 = phi i32 [ 109, %init.exit ], [ %indvars.iv.next18, %29 ] + %indvars.iv15 = phi i32 [ -75923, %init.exit ], [ %indvars.iv.next16, %29 ] + %indvars.iv13 = phi i32 [ 5593, %init.exit ], [ %indvars.iv.next14, %29 ] + %indvars.iv = phi i32 [ -262, %init.exit ], [ %indvars.iv.next, %29 ] + %10 = phi i32 [ 53, %init.exit ], [ %.pre-phi, %29 ] + %11 = zext i32 %indvars.iv19 to i33 + %12 = zext i32 %indvars.iv21 to i33 + %13 = mul i33 %11, %12 + %14 = icmp ult i32 %10, 27 + br i1 %14, label %.lr.ph, label %.preheader._crit_edge + +.preheader._crit_edge: ; preds = %.preheader + %.pre = add i32 %10, -1 + br label %29 + +.lr.ph: ; preds = %.preheader + %15 = zext i32 %indvars.iv23 to i33 + %16 = mul i33 %13, %15 + %17 = lshr i33 %16, 1 + %18 = lshr i33 %13, 1 + %19 = trunc i33 %17 to i32 + %20 = trunc i33 %18 to i32 + %21 = mul i32 %19, 1431655766 + %22 = mul i32 %indvars.iv17, %20 + %23 = add i32 %10, -1 + %24 = add i32 %10, 1 + %25 = getelementptr inbounds [100 x [100 x i32]]* %t, i32 0, i32 %24, i32 %23 + %.promoted = load i32* %25, align 4 + %26 = add i32 %.promoted, %indvars.iv15 + %27 = add i32 %26, %22 + %28 = add i32 %27, %21 + store i32 %28, i32* %25, align 4 + br label %29 + +.lr.ph.i3.preheader: ; preds = %29 + store i32 2, i32* %j, align 4 + store i32 %.lcssa69, i32* %k4, align 4 + br label %.lr.ph.i3 + +; <label>:29 ; preds = %.lr.ph, %.preheader._crit_edge + %.pre-phi = phi i32 [ %.pre, %.preheader._crit_edge ], [ %23, %.lr.ph ] + %.lcssa69 = phi i32 [ %10, %.preheader._crit_edge ], [ 27, %.lr.ph ] + %30 = icmp ugt i32 %.pre-phi, 2 + %indvars.iv.next = add i32 %indvars.iv, 6 + %indvars.iv.next14 = add i32 %indvars.iv13, %indvars.iv + %indvars.iv.next16 = add i32 %indvars.iv15, %indvars.iv13 + %indvars.iv.next18 = add i32 %indvars.iv17, -2 + %indvars.iv.next20 = add i32 %indvars.iv19, 1 + %indvars.iv.next22 = add i32 %indvars.iv21, 1 + %indvars.iv.next24 = add i32 %indvars.iv23, 1 + br i1 %30, label %.preheader, label %.lr.ph.i3.preheader + +.lr.ph.i3: ; preds = %.lr.ph.i3, %.lr.ph.i3.preheader + %sum.07.i = phi i32 [ %37, %.lr.ph.i3 ], [ 0, %.lr.ph.i3.preheader ] + %j.06.i = phi i32 [ %38, %.lr.ph.i3 ], [ 0, %.lr.ph.i3.preheader ] + %31 = and i32 %j.06.i, 1 + %32 = icmp eq i32 %31, 0 + %33 = getelementptr inbounds [100 x [100 x i32]]* %t, i32 0, i32 0, i32 %j.06.i + %34 = load i32* %33, align 4 + %35 = sub i32 0, %34 + %36 = select i1 %32, i32 %34, i32 %35 + %37 = add i32 %36, %sum.07.i + %38 = add i32 %j.06.i, 1 + %39 = icmp ult i32 %38, 10000 + br i1 %39, label %.lr.ph.i3, label %checkSum.exit + +checkSum.exit: ; preds = %.lr.ph.i3 + %40 = add i32 %37, 2 + %41 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str2, i32 0, i32 0), i32 %40) nounwind + ret i32 0 +} + +declare i32 @sscanf(i8* nocapture, i8* nocapture, ...) nounwind + +declare i32 @printf(i8* nocapture, ...) nounwind diff --git a/tests/cases/muli33_ta2.txt b/tests/cases/muli33_ta2.txt new file mode 100644 index 00000000..21e0231f --- /dev/null +++ b/tests/cases/muli33_ta2.txt @@ -0,0 +1 @@ +res = 3164 diff --git a/tests/cases/philoop.ll b/tests/cases/philoop_ta2.ll index 5036c7ba..5036c7ba 100644 --- a/tests/cases/philoop.ll +++ b/tests/cases/philoop_ta2.ll diff --git a/tests/cases/philoop.txt b/tests/cases/philoop_ta2.txt index d5117fe8..d5117fe8 100644 --- a/tests/cases/philoop.txt +++ b/tests/cases/philoop_ta2.txt diff --git a/tests/files.cpp b/tests/files.cpp index 04baa151..176cdb62 100644 --- a/tests/files.cpp +++ b/tests/files.cpp @@ -56,6 +56,9 @@ int main() fwrite(data, 1, 5, outf); fclose(outf); + FILE *devNull = fopen("/dev/null", "rb"); + assert(devNull); + char data2[10]; FILE *inf = fopen("go.out", "rb"); int num = fread(data2, 1, 10, inf); diff --git a/tests/full_es2_sdlproc.c b/tests/full_es2_sdlproc.c new file mode 100644 index 00000000..d9ac072b --- /dev/null +++ b/tests/full_es2_sdlproc.c @@ -0,0 +1,727 @@ +/* + * 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++) + glDrawElements(GL_TRIANGLE_STRIP, gear->strips[n].count, GL_FLOAT, gear->strips[n].first); + + /* 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" +" 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[]) +{ + if (argc == 12) SDL_GL_GetProcAddress("glWhatevah"); + + /* Initialize the window */ + glutInit(&argc, argv); + glutInitWindowSize(300, 300); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); + + glutCreateWindow("es2gears"); + + gears_idle(); + gears_init(); + gears_draw(); + + int result = 1; + REPORT_RESULT(); + + return 0; +} diff --git a/tests/gl_ps.c b/tests/gl_ps.c index 6ea0e3db..4fa79922 100644 --- a/tests/gl_ps.c +++ b/tests/gl_ps.c @@ -115,11 +115,11 @@ int main(int argc, char *argv[]) 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 @@ -135,30 +135,30 @@ int main(int argc, char *argv[]) glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -169,25 +169,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + shaders(); // Bind the texture to which subsequent calls refer to @@ -218,7 +218,7 @@ int main(int argc, char *argv[]) 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); @@ -226,8 +226,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/gl_ps_workaround.c b/tests/gl_ps_workaround.c deleted file mode 100644 index 1e2a5c41..00000000 --- a/tests/gl_ps_workaround.c +++ /dev/null @@ -1,230 +0,0 @@ -/******************************************************************* - * * - * 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 1 -#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> - -void shaders() { -#if USE_GLEW - glewInit(); -#endif - - GLint ok; - - const char *vertexShader = "void main(void) \n" - "{ \n" - " gl_Position = ftransform(); \n" - " gl_TexCoord[0] = gl_MultiTexCoord0; \n" - " gl_FrontColor = gl_Color; \n" - "} \n"; - const char *fragmentShader = "uniform sampler2D tex0; \n" - "void main(void) \n" - "{ \n" - " gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy); \n" - "} \n"; - - GLuint vs = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vs, 1, &vertexShader, NULL); - glCompileShader(vs); - glGetShaderiv(vs, GL_COMPILE_STATUS, &ok); - assert(ok); - - GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fs, 1, &fragmentShader, NULL); - glCompileShader(fs); - glGetShaderiv(fs, GL_COMPILE_STATUS, &ok); - assert(ok); - - GLuint program = glCreateProgram(); - - glAttachShader(program, vs); - glAttachShader(program, fs); - glLinkProgram(program); - glGetProgramiv(program, GL_LINK_STATUS, &ok); - assert(ok); - - glUseProgram(program); -} - -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_PROJECTION ); - GLfloat matrixData[] = { 2.0/640, 0, 0, 0, - 0, -2.0/480, 0, 0, - 0, 0, -1, 0, - -1, 1, 0, 1 }; - glLoadMatrixf(matrixData); // test loadmatrix - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - // Load the OpenGL texture - - GLuint texture; // Texture object handle - SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - - // Check that the image's width is a power of 2 - if ( (surface->w & (surface->w - 1)) != 0 ) { - printf("warning: image.bmp's width is not a power of 2\n"); - } - - // Also check if the height is a power of 2 - if ( (surface->h & (surface->h - 1)) != 0 ) { - printf("warning: image.bmp's height is not a power of 2\n"); - } - - // Have OpenGL generate a texture object handle for us - glGenTextures( 1, &texture ); - - // Bind the texture object - glBindTexture( GL_TEXTURE_2D, texture ); - - // Set the texture's stretching properties - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - - //SDL_LockSurface(surface); - - // Add some greyness - memset(surface->pixels, 0x66, surface->w*surface->h); - - // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); - - //SDL_UnlockSurface(surface); - } - else { - printf("SDL could not load image.bmp: %s\n", SDL_GetError()); - SDL_Quit(); - return 1; - } - - // Free the SDL_Surface only if it was successfully created - if ( surface ) { - SDL_FreeSurface( surface ); - } - - // Clear the screen before drawing - glClear( GL_COLOR_BUFFER_BIT ); - - shaders(); - - // Bind the texture to which subsequent calls refer to - glBindTexture( GL_TEXTURE_2D, texture ); - - // Use clientside vertex pointers to render two items. In this test we have each - // attribute in a separate buffer, packed (i.e. stride == 0) - GLfloat vertexData[] = { 10, 10, - 300, 10, - 300, 128, - 10, 128, - 410, 10, - 600, 10, - 630, 200, - 310, 250, - 100, 300, - 300, 300, - 300, 400, - 100, 400 }; - GLfloat textureData[] = { 0, 0, - 1, 0, - 1, 1, - 0, 1, - 0, 0.5, - 1, 0.5, - 1, 1, - 0.5, 1, - 0, 0, - 1, 0, - 1, 1, - 0, 1, }; - - glEnableClientState(GL_TEXTURE_2D); // XXX should be GL_TEXTURE_COORD_ARRAY); // XXX - glTexCoordPointer(2, GL_FLOAT, 0, textureData); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, vertexData); - - glDrawArrays(GL_QUADS, 0, 12); - - glDisableClientState(GL_TEXTURE_COORD_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 - - // Now we can delete the OpenGL texture and close down SDL - glDeleteTextures( 1, &texture ); - - SDL_Quit(); - - return 0; -} diff --git a/tests/gl_ps_workaround2.c b/tests/gl_ps_workaround2.c deleted file mode 100644 index e5bd2fd1..00000000 --- a/tests/gl_ps_workaround2.c +++ /dev/null @@ -1,230 +0,0 @@ -/******************************************************************* - * * - * 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 1 -#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> - -void shaders() { -#if USE_GLEW - glewInit(); -#endif - - GLint ok; - - const char *vertexShader = "void main(void) \n" - "{ \n" - " gl_Position = ftransform(); \n" - " gl_TexCoord[0] = gl_MultiTexCoord0; \n" - " gl_FrontColor = gl_Color; \n" - "} \n"; - const char *fragmentShader = "uniform sampler2D tex0; \n" - "void main(void) \n" - "{ \n" - " gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy); \n" - "} \n"; - - GLuint vs = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vs, 1, &vertexShader, NULL); - glCompileShader(vs); - glGetShaderiv(vs, GL_COMPILE_STATUS, &ok); - assert(ok); - - GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fs, 1, &fragmentShader, NULL); - glCompileShader(fs); - glGetShaderiv(fs, GL_COMPILE_STATUS, &ok); - assert(ok); - - GLuint program = glCreateProgram(); - - glAttachShader(program, vs); - glAttachShader(program, fs); - glLinkProgram(program); - glGetProgramiv(program, GL_LINK_STATUS, &ok); - assert(ok); - - glUseProgram(program); -} - -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_PROJECTION ); - GLfloat matrixData[] = { 2.0/640, 0, 0, 0, - 0, -2.0/480, 0, 0, - 0, 0, -1, 0, - -1, 1, 0, 1 }; - glLoadMatrixf(matrixData); // test loadmatrix - - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - // Load the OpenGL texture - - GLuint texture; // Texture object handle - SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - - // Check that the image's width is a power of 2 - if ( (surface->w & (surface->w - 1)) != 0 ) { - printf("warning: image.bmp's width is not a power of 2\n"); - } - - // Also check if the height is a power of 2 - if ( (surface->h & (surface->h - 1)) != 0 ) { - printf("warning: image.bmp's height is not a power of 2\n"); - } - - // Have OpenGL generate a texture object handle for us - glGenTextures( 1, &texture ); - - // Bind the texture object - glBindTexture( GL_TEXTURE_2D, texture ); - - // Set the texture's stretching properties - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - - //SDL_LockSurface(surface); - - // Add some greyness - memset(surface->pixels, 0x66, surface->w*surface->h); - - // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); - - //SDL_UnlockSurface(surface); - } - else { - printf("SDL could not load image.bmp: %s\n", SDL_GetError()); - SDL_Quit(); - return 1; - } - - // Free the SDL_Surface only if it was successfully created - if ( surface ) { - SDL_FreeSurface( surface ); - } - - // Clear the screen before drawing - glClear( GL_COLOR_BUFFER_BIT ); - - shaders(); - - // Bind the texture to which subsequent calls refer to - glBindTexture( GL_TEXTURE_2D, texture ); - - // Use clientside vertex pointers to render two items. In this test we have each - // attribute in a separate buffer, packed (i.e. stride == 0) - GLfloat vertexData[] = { 10, 10, - 300, 10, - 300, 128, - 10, 128, - 410, 10, - 600, 10, - 630, 200, - 310, 250, - 100, 300, - 300, 300, - 300, 400, - 100, 400 }; - GLfloat textureData[] = { 0, 0, - 1, 0, - 1, 1, - 0, 1, - 0, 0.5, - 1, 0.5, - 1, 1, - 0.5, 1, - 0, 0, - 1, 0, - 1, 1, - 0, 1, }; - - glEnable(GL_TEXTURE_2D); // XXX should be GL_TEXTURE_COORD_ARRAY); and also glEnableClientState! XXX two workarounds here - glTexCoordPointer(2, GL_FLOAT, 0, textureData); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, vertexData); - - glDrawArrays(GL_QUADS, 0, 12); - - glDisableClientState(GL_TEXTURE_COORD_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 - - // Now we can delete the OpenGL texture and close down SDL - glDeleteTextures( 1, &texture ); - - SDL_Quit(); - - return 0; -} diff --git a/tests/glbegin_points.c b/tests/glbegin_points.c index b28cca4e..9128a4f5 100644 --- a/tests/glbegin_points.c +++ b/tests/glbegin_points.c @@ -46,14 +46,12 @@ int main(int argc, char *argv[]) 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -66,30 +64,30 @@ int main(int argc, char *argv[]) glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -151,7 +149,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -159,8 +157,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/runner.py b/tests/runner.py index 720f434e..47c1f1be 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -904,26 +904,26 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows void interface_clock_changed() { - UINT8 m_divshift; - INT32 m_divisor; + UINT8 m_divshift; + INT32 m_divisor; - //INT64 attos = m_attoseconds_per_cycle; - INT64 attos = 279365114840; - m_divshift = 0; - while (attos >= (1UL << 31)) - { - m_divshift++; - printf("m_divshift is %i, on %Ld >?= %lu\n", m_divshift, attos, 1UL << 31); - attos >>= 1; - } - m_divisor = attos; + //INT64 attos = m_attoseconds_per_cycle; + INT64 attos = 279365114840; + m_divshift = 0; + while (attos >= (1UL << 31)) + { + m_divshift++; + printf("m_divshift is %i, on %Ld >?= %lu\n", m_divshift, attos, 1UL << 31); + attos >>= 1; + } + m_divisor = attos; - printf("m_divisor is %i\n",m_divisor); + printf("m_divisor is %i\n",m_divisor); } int main() { - interface_clock_changed(); - return 0; + interface_clock_changed(); + return 0; } ''' self.do_run(src, '''m_divshift is 1, on 279365114840 >?= 2147483648 @@ -997,8 +997,8 @@ m_divisor is 1091269979 volatile UINT64 testu64a = 14746250828952703000U; while ((UINT64)testu32a * (UINT64)bigu32 < testu64a) { - printf("testu64a is %llu\n", testu64a); - testu64a /= 2; + printf("testu64a is %llu\n", testu64a); + testu64a /= 2; } return 0; @@ -1456,28 +1456,28 @@ c5,de,15,8a quint64 v = strtoull("4433ffeeddccbb00", NULL, 16); printf("%lld\n", v); - const string string64bitInt = "4433ffeeddccbb00"; - stringstream s(string64bitInt); - quint64 int64bitInt = 0; + const string string64bitInt = "4433ffeeddccbb00"; + stringstream s(string64bitInt); + quint64 int64bitInt = 0; printf("1\n"); - s >> hex >> int64bitInt; + s >> hex >> int64bitInt; printf("2\n"); - stringstream out; - out << hex << qbswap(int64bitInt); + stringstream out; + out << hex << qbswap(int64bitInt); - cout << out.str() << endl; - cout << hex << int64bitInt << endl; - cout << string64bitInt << endl; + cout << out.str() << endl; + cout << hex << int64bitInt << endl; + cout << string64bitInt << endl; - if (out.str() != "bbccddeeff3344") - { - cout << "Failed!" << endl; - } - else - { - cout << "Succeeded!" << endl; - } + if (out.str() != "bbccddeeff3344") + { + cout << "Failed!" << endl; + } + else + { + cout << "Succeeded!" << endl; + } return 0; } @@ -4030,15 +4030,15 @@ def process(filename): // see related things in openjpeg typedef struct opj_mqc_state { - unsigned int qeval; - int mps; - struct opj_mqc_state *nmps; - struct opj_mqc_state *nlps; + unsigned int qeval; + int mps; + struct opj_mqc_state *nmps; + struct opj_mqc_state *nlps; } opj_mqc_state_t; static opj_mqc_state_t mqc_states[2] = { - {0x5600, 0, &mqc_states[2], &mqc_states[3]}, - {0x5602, 1, &mqc_states[3], &mqc_states[2]}, + {0x5600, 0, &mqc_states[2], &mqc_states[3]}, + {0x5602, 1, &mqc_states[3], &mqc_states[2]}, }; int main() { @@ -4533,6 +4533,8 @@ The current type of b is: 9 self.do_run(src, '*1*', force_c=True) def test_strtoll_hex(self): + if self.emcc_args is None: return self.skip('requires emcc') + # tests strtoll for hex strings (0x...) src = r''' #include <stdio.h> @@ -4559,6 +4561,8 @@ The current type of b is: 9 self.do_run(src, '111111') def test_strtoll_dec(self): + if self.emcc_args is None: return self.skip('requires emcc') + # tests strtoll for decimal strings (0x...) src = r''' #include <stdio.h> @@ -4585,6 +4589,8 @@ The current type of b is: 9 self.do_run(src, '111111') def test_strtoll_bin(self): + if self.emcc_args is None: return self.skip('requires emcc') + # tests strtoll for binary strings (0x...) src = r''' #include <stdio.h> @@ -4606,6 +4612,8 @@ The current type of b is: 9 self.do_run(src, '111') def test_strtoll_oct(self): + if self.emcc_args is None: return self.skip('requires emcc') + # tests strtoll for decimal strings (0x...) src = r''' #include <stdio.h> @@ -4807,25 +4815,25 @@ The current type of b is: 9 typedef struct { - int (*f)(void *); - void *d; - char s[16]; + int (*f)(void *); + void *d; + char s[16]; } LMEXFunctionStruct; int f(void *user) { - return 0; + return 0; } static LMEXFunctionStruct const a[] = { - {f, (void *)(int)'a', "aa"} + {f, (void *)(int)'a', "aa"} }; int main() { printf("ok\n"); - return a[0].f(a[0].d); + return a[0].f(a[0].d); } ''' self.do_run(src, 'ok\n') @@ -6824,7 +6832,7 @@ def process(filename): printf("f_blocks: %lu\n", s.f_blocks); printf("f_bfree: %lu\n", s.f_bfree); printf("f_bavail: %lu\n", s.f_bavail); - printf("f_files: %lu\n", s.f_files); + printf("f_files: %d\n", s.f_files > 5); printf("f_ffree: %lu\n", s.f_ffree); printf("f_favail: %lu\n", s.f_favail); printf("f_fsid: %lu\n", s.f_fsid); @@ -6842,7 +6850,7 @@ def process(filename): f_blocks: 1000000 f_bfree: 500000 f_bavail: 500000 - f_files: 10 + f_files: 1 f_ffree: 1000000 f_favail: 1000000 f_fsid: 42 @@ -10307,6 +10315,8 @@ f.close() assert not os.path.exists('a.out') and not os.path.exists('a.exe'), 'Must not leave unneeded linker stubs' def test_symlink(self): + if os.name == 'nt': + return self.skip('Windows FS does not need to be tested for symlinks support, since it does not have them.') open(os.path.join(self.get_dir(), 'foobar.xxx'), 'w').write('int main(){ return 0; }') os.symlink(os.path.join(self.get_dir(), 'foobar.xxx'), os.path.join(self.get_dir(), 'foobar.c')) Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'foobar.c'), '-o', os.path.join(self.get_dir(), 'foobar')], stdout=PIPE, stderr=PIPE).communicate() @@ -10461,8 +10471,8 @@ f.close() #define _TESTA_H_ class TestA { - public: - TestA(); + public: + TestA(); }; #endif @@ -10472,8 +10482,8 @@ f.close() #define _TESTB_H_ class TestB { - public: - TestB(); + public: + TestB(); }; #endif @@ -10483,7 +10493,7 @@ f.close() #include <testa.h> TestA::TestA() { - printf("TestA\n"); + printf("TestA\n"); } ''') open('testb.cpp', 'w').write(r''' @@ -10493,8 +10503,8 @@ f.close() /* */ TestB::TestB() { - printf("TestB\n"); - TestA* testa = new TestA(); + printf("TestB\n"); + TestA* testa = new TestA(); } ''') open('main.cpp', 'w').write(r''' @@ -10505,9 +10515,9 @@ f.close() /* */ int main(int argc, char** argv) { - printf("Main\n"); - TestA* testa = new TestA(); - TestB* testb = new TestB(); + printf("Main\n"); + TestA* testa = new TestA(); + TestB* testb = new TestB(); } ''') @@ -12436,6 +12446,9 @@ elif 'browser' in str(sys.argv): self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true') assert ('var GLEmulation' in open(self.in_dir('something.html')).read()) == emulation, "emulation code should be added when asked for" + def test_fulles2_sdlproc(self): + self.btest('full_es2_sdlproc.c', '1', args=['-s', 'GL_TESTING=1', '-DHAVE_BUILTIN_SINCOS', '-s', 'FULL_ES2=1']) + def test_glgears_deriv(self): self.reftest(path_from_root('tests', 'gears.png')) Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles_deriv.c'), '-o', 'something.html', '-s', 'GL_TESTING=1', @@ -12549,14 +12562,6 @@ 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_packed.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png']) - def test_gl_ps_workaround(self): - shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('gl_ps_workaround.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png']) - - def test_gl_ps_workaround2(self): - shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) - self.btest('gl_ps_workaround2.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png']) - def test_gl_ps_strides(self): 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']) @@ -14005,7 +14010,7 @@ if __name__ == '__main__': which = map(lambda mode: mode+'.'+test, test_modes) else: which = [which] - + print >> sys.stderr, ','.join(which) for test in which: print >> sys.stderr, 'will skip "%s"' % test diff --git a/tests/s3tc.c b/tests/s3tc.c index c2736feb..16ee783f 100644 --- a/tests/s3tc.c +++ b/tests/s3tc.c @@ -63,14 +63,12 @@ int main(int argc, char *argv[]) const char *exts = (const char *)glGetString(GL_EXTENSIONS); assert(hasext(exts, "GL_ARB_texture_compression")); assert(hasext(exts, "GL_EXT_texture_compression_s3tc")); - + // 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -110,7 +108,7 @@ int main(int argc, char *argv[]) // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -143,7 +141,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(1500); @@ -151,8 +149,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/s3tc_crunch.c b/tests/s3tc_crunch.c index 57974109..90ed02d9 100644 --- a/tests/s3tc_crunch.c +++ b/tests/s3tc_crunch.c @@ -63,14 +63,12 @@ int main(int argc, char *argv[]) const char *exts = (const char *)glGetString(GL_EXTENSIONS); assert(hasext(exts, "GL_ARB_texture_compression")); assert(hasext(exts, "GL_EXT_texture_compression_s3tc")); - + // 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -158,7 +156,7 @@ int main(int argc, char *argv[]) // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -195,7 +193,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(1500); @@ -203,8 +201,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_fog_density.c b/tests/sdl_fog_density.c index 95773419..cab6a4d2 100644 --- a/tests/sdl_fog_density.c +++ b/tests/sdl_fog_density.c @@ -47,14 +47,12 @@ int main(int argc, char *argv[]) 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -63,33 +61,33 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1000, 1000 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -148,9 +146,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -168,7 +164,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(30000); @@ -176,8 +172,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_fog_exp2.c b/tests/sdl_fog_exp2.c index a09a5e3d..dba0c708 100644 --- a/tests/sdl_fog_exp2.c +++ b/tests/sdl_fog_exp2.c @@ -47,14 +47,12 @@ int main(int argc, char *argv[]) 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -63,33 +61,33 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1000, 1000 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -149,9 +147,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -169,7 +165,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(30000); @@ -177,8 +173,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_fog_linear.c b/tests/sdl_fog_linear.c index 8fc18b7c..f0805650 100644 --- a/tests/sdl_fog_linear.c +++ b/tests/sdl_fog_linear.c @@ -47,14 +47,12 @@ int main(int argc, char *argv[]) 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -63,33 +61,33 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1000, 1000 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -150,9 +148,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -170,7 +166,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(30000); @@ -178,8 +174,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_fog_negative.c b/tests/sdl_fog_negative.c index 2d589a47..1ede63a7 100644 --- a/tests/sdl_fog_negative.c +++ b/tests/sdl_fog_negative.c @@ -47,14 +47,12 @@ int main(int argc, char *argv[]) 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -63,33 +61,33 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1000, 1000 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -147,9 +145,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, -1 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -167,7 +163,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(30000); @@ -175,8 +171,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_fog_simple.c b/tests/sdl_fog_simple.c index be023593..6c052bf5 100644 --- a/tests/sdl_fog_simple.c +++ b/tests/sdl_fog_simple.c @@ -47,14 +47,10 @@ int main(int argc, char *argv[]) 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 ); @@ -63,33 +59,38 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1000, 1000 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + + // Delay Enable to after MatrixMode to assure we've activated + // immediate mode. Otherwise, we don't properly record that + // TEXTURE_2D is enabled for imm mode emulation. + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +101,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -147,9 +148,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 1 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -167,7 +166,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(30000); @@ -175,8 +174,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_ogl.c b/tests/sdl_ogl.c index 6b6a5b4a..e7071dcd 100644 --- a/tests/sdl_ogl.c +++ b/tests/sdl_ogl.c @@ -46,14 +46,12 @@ int main(int argc, char *argv[]) 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -62,33 +60,33 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1, 1 ); - + glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -99,25 +97,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -140,9 +138,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -160,7 +156,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -168,8 +164,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_ogl_defaultMatrixMode.c b/tests/sdl_ogl_defaultMatrixMode.c index 0da0a326..eec2a831 100644 --- a/tests/sdl_ogl_defaultMatrixMode.c +++ b/tests/sdl_ogl_defaultMatrixMode.c @@ -46,14 +46,12 @@ int main(int argc, char *argv[]) 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -66,30 +64,30 @@ int main(int argc, char *argv[]) glLoadIdentity(); glOrtho( 0, 640, 480, 0, -1, 1 ); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -141,9 +139,7 @@ int main(int argc, char *argv[]) glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 ); glEnd(); -#if !EMSCRIPTEN glDisable(GL_TEXTURE_2D); -#endif glColor3ub(90, 255, 255); glBegin( GL_QUADS ); @@ -161,7 +157,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -169,8 +165,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/tests/sdl_ogl_p.c b/tests/sdl_ogl_p.c index fcc53a40..1889d926 100644 --- a/tests/sdl_ogl_p.c +++ b/tests/sdl_ogl_p.c @@ -46,14 +46,12 @@ int main(int argc, char *argv[]) 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 + + glEnable( GL_TEXTURE_2D ); // Needed when we're using the fixed-function pipeline. glViewport( 0, 0, 640, 480 ); @@ -66,30 +64,30 @@ int main(int argc, char *argv[]) glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - + // Load the OpenGL texture GLuint texture; // Texture object handle SDL_Surface *surface; // Gives us the information to make the texture - - if ( (surface = IMG_Load("screenshot.png")) ) { - + + if ( (surface = IMG_Load("screenshot.png")) ) { + // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: image.bmp's width is not a power of 2\n"); } - + // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: image.bmp's height is not a power of 2\n"); } - + // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); - + // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); - + // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -100,25 +98,25 @@ int main(int argc, char *argv[]) memset(surface->pixels, 0x66, surface->w*surface->h); // Edit the texture object's image data using the information SDL_Surface gives us - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels ); //SDL_UnlockSurface(surface); - } + } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); SDL_Quit(); return 1; - } - + } + // Free the SDL_Surface only if it was successfully created - if ( surface ) { + if ( surface ) { SDL_FreeSurface( surface ); } - + // Clear the screen before drawing glClear( GL_COLOR_BUFFER_BIT ); - + // Bind the texture to which subsequent calls refer to glBindTexture( GL_TEXTURE_2D, texture ); @@ -151,7 +149,7 @@ int main(int argc, char *argv[]) glEnd(); SDL_GL_SwapBuffers(); - + #if !EMSCRIPTEN // Wait for 3 seconds to give us a chance to see the image SDL_Delay(3000); @@ -159,8 +157,8 @@ int main(int argc, char *argv[]) // Now we can delete the OpenGL texture and close down SDL glDeleteTextures( 1, &texture ); - + SDL_Quit(); - + return 0; } diff --git a/third_party/lzma.js/lzip/Makefile b/third_party/lzma.js/lzip/Makefile index ca6a6ef7..8a5baee3 100644 --- a/third_party/lzma.js/lzip/Makefile +++ b/third_party/lzma.js/lzip/Makefile @@ -16,7 +16,8 @@ datadir = $(prefix)/share infodir = $(datadir)/info mandir = $(datadir)/man sysconfdir = $(prefix)/etc -CPPFLAGS = -DDECODER_ONLY=$(DECODER_ONLY) +CXX = g++ +CPPFLAGS = CXXFLAGS = -Wall -W -O2 LDFLAGS = @@ -27,16 +28,16 @@ INSTALL_DATA = $(INSTALL) -p -m 644 INSTALL_DIR = $(INSTALL) -d -m 755 SHELL = /bin/sh -objs = decoder.o encoder.o fast_encoder.o main.o -recobjs = decoder.o lziprecover.o -unzobjs = unzcrash.o +objs = arg_parser.o decoder.o encoder.o fast_encoder.o main.o +recobjs = arg_parser.o decoder.o lziprecover.o +unzobjs = arg_parser.o unzcrash.o .PHONY : all install install-info install-man install-strip \ uninstall uninstall-info uninstall-man \ doc info man check dist clean distclean -all : $(progname) +all : $(progname) lziprecover $(progname) : $(objs) $(CXX) $(LDFLAGS) -o $@ $(objs) @@ -63,12 +64,13 @@ unzcrash.o : testsuite/unzcrash.cc $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< $(objs) : Makefile +arg_parser.o : arg_parser.h decoder.o : lzip.h decoder.h encoder.o : lzip.h encoder.h fast_encoder.o : lzip.h encoder.h fast_encoder.h -main.o : lzip.h decoder.h encoder.h fast_encoder.h -lziprecover.o : lzip.h decoder.h Makefile -unzcrash.o : Makefile +main.o : arg_parser.h lzip.h decoder.h encoder.h fast_encoder.h +lziprecover.o : arg_parser.h lzip.h decoder.h Makefile +unzcrash.o : arg_parser.h Makefile doc : info man diff --git a/tools/shared.py b/tools/shared.py index 7d956293..799a5bbe 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -295,7 +295,7 @@ def check_node_version(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.4.3' +EMSCRIPTEN_VERSION = '1.4.7' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() |