diff options
-rwxr-xr-x | emcc | 6 | ||||
-rwxr-xr-x | emscripten.py | 2 | ||||
-rw-r--r-- | src/library_gl.js | 213 | ||||
-rw-r--r-- | src/library_sdl.js | 4 | ||||
-rw-r--r-- | system/include/libc/sys/types.h | 8 | ||||
-rw-r--r-- | tests/cubegeom.c | 12 | ||||
-rw-r--r-- | tests/gl_ps.c | 217 | ||||
-rw-r--r-- | tests/gl_ps.png | bin | 0 -> 203535 bytes | |||
-rwxr-xr-x | tests/runner.py | 7 | ||||
-rw-r--r-- | tests/sdl_ogl_p.c | 8 | ||||
-rw-r--r-- | tools/shared.py | 18 |
11 files changed, 396 insertions, 99 deletions
@@ -722,9 +722,9 @@ try: # dlmalloc def create_dlmalloc(): if DEBUG: print >> sys.stderr, 'emcc: building dlmalloc for cache' - execute(['python', shared.EMCC, shared.path_from_root('system', 'lib', 'dlmalloc.c'), '-g', '-o', in_temp('dlmalloc.o')], stdout=stdout, stderr=stderr) + execute(shared.ENV_PREFIX + ['python', shared.EMCC, shared.path_from_root('system', 'lib', 'dlmalloc.c'), '-g', '-o', in_temp('dlmalloc.o')], stdout=stdout, stderr=stderr) # we include the libc++ new stuff here, so that the common case of using just new/delete is quick to link - execute(['python', shared.EMXX, shared.path_from_root('system', 'lib', 'libcxx', 'new.cpp'), '-g', '-o', in_temp('new.o')], stdout=stdout, stderr=stderr) + execute(shared.ENV_PREFIX + ['python', shared.EMXX, shared.path_from_root('system', 'lib', 'libcxx', 'new.cpp'), '-g', '-o', in_temp('new.o')], stdout=stdout, stderr=stderr) shared.Building.link([in_temp('dlmalloc.o'), in_temp('new.o')], in_temp('dlmalloc_full.o')) return in_temp('dlmalloc_full.o') def fix_dlmalloc(): @@ -846,7 +846,7 @@ try: if AUTODEBUG: if DEBUG: print >> sys.stderr, 'emcc: autodebug' - execute(['python', shared.AUTODEBUGGER, final, final + '.ad.ll']) + execute(shared.ENV_PREFIX + ['python', shared.AUTODEBUGGER, final, final + '.ad.ll']) final += '.ad.ll' if DEBUG: save_intermediate('autodebug', 'll') diff --git a/emscripten.py b/emscripten.py index 45c9f418..044d6cd9 100755 --- a/emscripten.py +++ b/emscripten.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python ''' You should normally never use this! Use emcc instead. diff --git a/src/library_gl.js b/src/library_gl.js index 29e9687c..d3011c69 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -967,9 +967,13 @@ var LibraryGL = { } } if (source.indexOf('gl_Color') >= 0) { - source = 'attribute vec4 a_color; \n\ - varying vec4 v_color; \n' + - source.replace(/gl_Color/g, 'a_color').replace(/gl_FrontColor/g, 'v_color'); + source = 'varying vec4 v_color; \n' + + source.replace(/gl_Color/g, 'vec4(1, 1, 1, 1)').replace(/gl_FrontColor/g, 'v_color'); // XXX gl_Color can be either an attribute, or + // from glColor, and we don't know which here. + // For now, just use white + //source = 'attribute vec4 a_color; \n\ + // varying vec4 v_color; \n' + + // source.replace(/gl_Color/g, 'a_color').replace(/gl_FrontColor/g, 'v_color'); } if (source.indexOf('gl_FogFragCoord') >= 0) { source = 'varying float v_fogCoord; \n' + @@ -1034,6 +1038,32 @@ var LibraryGL = { glUseProgram(program); } + var glDeleteProgram = _glDeleteProgram; + _glDeleteProgram = function(program) { + glDeleteProgram(program); + if (program == GL.currProgram) GL.currProgram = 0; + }; + + var glBindBuffer = _glBindBuffer; + _glBindBuffer = function(target, buffer) { + glBindBuffer(target, buffer); + if (target == Module.ctx.ARRAY_BUFFER) { + GL.currArrayBuffer = buffer; + } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { + GL.currElementArrayBuffer = buffer; + } + }; + + var glDeleteBuffers = _glDeleteBuffers; + _glDeleteBuffers = function(n, buffers) { + glDeleteBuffers(n, buffers); + for (var i = 0; i < n; i++) { + var buffer = {{{ makeGetValue('buffers', 'i*4', 'i32') }}}; + if (buffer == GL.currArrayBuffer) GL.currArrayBuffer = 0; + if (buffer == GL.currElementArrayBuffer) GL.currElementArrayBuffer = 0; + } + }; + var glGetFloatv = _glGetFloatv; _glGetFloatv = function(pname, params) { if (pname == 0x0BA6) { // GL_MODELVIEW_MATRIX @@ -1204,11 +1234,14 @@ var LibraryGL = { }, setRenderer: function(renderer) { - this.renderer = renderer; - if (this.renderers[renderer]) return this.renderers[renderer]; - - this.createRenderer(renderer); - return this.renderers[renderer]; + var name = renderer; + if (GL.currProgram && renderer[0] != 'U') { + name = 'UD' + GL.currProgram + '|' + renderer; // user-defined program renderer + } + this.renderer = name; + if (this.renderers[name]) return this.renderers[name]; + this.renderers[name] = this.createRenderer(renderer); + return this.renderers[name]; }, createRenderer: function(renderer) { @@ -1228,7 +1261,7 @@ var LibraryGL = { textureOffset = vertexSize; } } else { - throw 'Cannot create shader rendederer for ' + renderer + ' because of ' + which; + console.log('Warning: Ignoring renderer attribute ' + which); } vertexSize += size * 4; // XXX assuming float } @@ -1236,7 +1269,7 @@ var LibraryGL = { // TODO: verify vertexSize is equal to the stride in enabled client arrays // XXX TODO: use bufferSubData to prevent reallocation of new buffers? Or all on GPU and doesn't matter? Anyhow, use DYNAMIC as hint var useCurrProgram = !!GL.currProgram; - this.renderers[renderer] = { + var ret = { vertexSize: vertexSize, hasTexture: textureSize > 0, init: function() { @@ -1253,24 +1286,24 @@ var LibraryGL = { this.vertexShader = Module.ctx.createShader(Module.ctx.VERTEX_SHADER); var zero = positionSize == 2 ? '0, ' : ''; Module.ctx.shaderSource(this.vertexShader, 'attribute vec' + positionSize + ' a_position; \n' + - 'attribute vec2 a_texCoord; \n' + + 'attribute vec2 a_texCoord0; \n' + (textureSize ? 'varying vec2 v_texCoord; \n' : '') + 'uniform mat4 u_modelView; \n' + 'uniform mat4 u_projection; \n' + 'void main() \n' + '{ \n' + ' gl_Position = u_projection * (u_modelView * vec4(a_position, ' + zero + '1.0)); \n' + - (textureSize ? 'v_texCoord = a_texCoord; \n' : '') + + (textureSize ? 'v_texCoord = a_texCoord0; \n' : '') + '} \n'); Module.ctx.compileShader(this.vertexShader); 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 s_texture; \n' + + 'uniform sampler2D u_texture; \n' + 'void main() \n' + '{ \n' + - (textureSize ? 'gl_FragColor = texture2D( s_texture, v_texCoord );\n' : + (textureSize ? 'gl_FragColor = texture2D( u_texture, v_texCoord );\n' : 'gl_FragColor = vec4(0.8, 0.1, 1.0, 1.0);') + '} \n'); Module.ctx.compileShader(this.fragmentShader); @@ -1282,8 +1315,8 @@ var LibraryGL = { } this.positionLocation = Module.ctx.getAttribLocation(this.program, 'a_position'); - this.texCoordLocation = Module.ctx.getAttribLocation(this.program, 'a_texCoord'); - this.textureLocation = Module.ctx.getUniformLocation(this.program, 's_texture'); + this.texCoordLocation = Module.ctx.getAttribLocation(this.program, 'a_texCoord0'); + this.textureLocation = Module.ctx.getUniformLocation(this.program, 'u_texture'); this.modelViewLocation = Module.ctx.getUniformLocation(this.program, 'u_modelView'); this.projectionLocation = Module.ctx.getUniformLocation(this.program, 'u_projection'); }, @@ -1301,16 +1334,19 @@ var LibraryGL = { } Module.ctx.enableVertexAttribArray(this.positionLocation); - 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 (!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); + } Module.ctx.uniformMatrix4fv(this.modelViewLocation, false, GL.immediate.matrix['m']); Module.ctx.uniformMatrix4fv(this.projectionLocation, false, GL.immediate.matrix['p']); } }; - this.renderers[renderer].init(); + ret.init(); + return ret; }, // Main functions @@ -1332,43 +1368,62 @@ var LibraryGL = { Module.ctx.drawArrays(mode, first, count); return; } -#if ASSERTIONS assert(first == 0); // TODO -#endif - // Client attributes are to be used here, emulate that - var stride = 0, bytes = 0, attributes = [], start, renderer = ''; - for (var i = 0; i < GL.immediate.NUM_ATTRIBUTES; i++) { - if (GL.immediate.enabledClientAttributes[i]) attributes.push(GL.immediate.clientAttributes[i]); + + var renderer = GL.immediate.prepareClientAttributes(count); + GL.immediate.mode = mode; + GL.immediate.setRenderer(renderer); + GL.immediate.flush(); + }; + + _glDrawElements = function(mode, count, type, indices) { + if (GL.immediate.totalEnabledClientAttributes == 0) { + Module.ctx.drawElements(mode, count, type, indices); + return; } - attributes.sort(function(x, y) { return !x ? (!y ? 0 : 1) : (!y ? -1 : (x.pointer - y.pointer)) }); - start = attributes[0].pointer; - for (var i = 0; i < attributes.length; i++) { - var attribute = attributes[i]; - if (!attribute) break; + + var renderer = GL.immediate.prepareClientAttributes(count); + GL.immediate.mode = mode; + GL.immediate.setRenderer(renderer); + GL.immediate.flush(count); + }; + }, + + prepareClientAttributes: function(count) { + // Client attributes are to be used here, emulate that + var stride = 0, bytes = 0, attributes = [], start, renderer = ''; + for (var i = 0; i < GL.immediate.NUM_ATTRIBUTES; i++) { + if (GL.immediate.enabledClientAttributes[i]) attributes.push(GL.immediate.clientAttributes[i]); + } + attributes.sort(function(x, y) { return !x ? (!y ? 0 : 1) : (!y ? -1 : (x.pointer - y.pointer)) }); + start = attributes[0].pointer; + for (var i = 0; i < attributes.length; i++) { + var attribute = attributes[i]; + if (!attribute) break; #if ASSERTIONS - assert(attribute.stride); - assert(stride == 0 || stride == attribute.stride); // must all be in the same buffer + assert(attribute.stride); + assert(stride == 0 || stride == attribute.stride); // must all be in the same buffer #endif - stride = attribute.stride; - bytes += attribute.size * 4 * count; // XXX assuming float - renderer += attribute.name; - } - for (var i = 0; i < attributes.length; i++) { - var attribute = attributes[i]; - if (!attribute) break; - attribute.offset = attribute.pointer - start; + stride = attribute.stride; + bytes += attribute.size * 4 * count; // XXX assuming float + renderer += attribute.name; + } + for (var i = 0; i < attributes.length; i++) { + var attribute = attributes[i]; + if (!attribute) break; + attribute.offset = attribute.pointer - start; #if ASSERTIONS - assert(0 <= attribute.offset && attribute.offset < stride); // must all be in the same buffer + assert(0 <= attribute.offset && attribute.offset < stride); // must all be in the same buffer #endif - } - GL.immediate.vertexData = {{{ makeHEAPView('F32', 'start', 'start + bytes') }}}; // XXX assuming float - GL.immediate.vertexCounter = bytes / 4; // XXX assuming float - GL.immediate.mode = mode; - GL.immediate.setRenderer(renderer); - GL.immediate.flush(); - }; + } + + GL.immediate.vertexData = {{{ makeHEAPView('F32', 'start', 'start + bytes') }}}; // XXX assuming float + GL.immediate.vertexCounter = bytes / 4; // XXX assuming float + + return renderer; }, - flush: function() { + + flush: function(numProvidedIndexes) { var renderer = this.setRenderer(this.renderer); // Generate index data in a format suitable for GLES 2.0/WebGL @@ -1377,7 +1432,9 @@ var LibraryGL = { assert(numVertexes % 1 == 0); var numIndexes = 0; - if (GL.immediate.mode > 6) { // above GL_TRIANGLE_FAN are the non-GL ES modes + if (numProvidedIndexes) { + numIndexes = numProvidedIndexes; + } else if (GL.immediate.mode > 6) { // above GL_TRIANGLE_FAN are the non-GL ES modes if (GL.immediate.mode == 7) { // GL_QUADS var numQuads = numVertexes / 4; assert(numQuads % 1 == 0); @@ -1399,22 +1456,34 @@ var LibraryGL = { Module.ctx.bufferData(Module.ctx.ELEMENT_ARRAY_BUFFER, this.indexData.subarray(0, numIndexes), Module.ctx.STATIC_DRAW); } - Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.vertexObject); - Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, this.vertexData.subarray(0, this.vertexCounter), Module.ctx.STATIC_DRAW); + if (!GL.currArrayBuffer) { + Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.vertexObject); + Module.ctx.bufferData(Module.ctx.ARRAY_BUFFER, this.vertexData.subarray(0, this.vertexCounter), Module.ctx.STATIC_DRAW); + } // Render - Module.ctx.useProgram(renderer.program); - Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, this.vertexObject); + if (!GL.currProgram) { + Module.ctx.useProgram(renderer.program); + } renderer.prepare(); if (numIndexes) { - Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.indexObject); + if (!numProvidedIndexes) { + Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, this.indexObject); + } Module.ctx.drawElements(Module.ctx.TRIANGLES, numIndexes, Module.ctx.UNSIGNED_SHORT, 0); } else { Module.ctx.drawArrays(GL.immediate.mode, 0, numVertexes); } + if (!GL.currArrayBuffer) { + Module.ctx.bindBuffer(Module.ctx.ARRAY_BUFFER, null); + } + if (!GL.currProgram) { + Module.ctx.useProgram(null); + } + this.vertexCounter = 0; } }, @@ -1518,22 +1587,22 @@ var LibraryGL = { _glEnableClientState(cap, 1); }, - glTexCoordPointer: function(size, type, stride, pointer) { - GL.immediate.setClientAttribute('T' + GL.immediate.clientActiveTexture, size, type, stride, pointer); - }, glVertexPointer__deps: ['$GLEmulation'], // if any pointers are used, glVertexPointer must be, and if it is, then we need emulation glVertexPointer: function(size, type, stride, pointer) { GL.immediate.setClientAttribute('V', size, type, stride, pointer); }, - glNormalPointer: function(size, type, stride, pointer) { - GL.immediate.setClientAttribute('N', size, type, stride, pointer); + glTexCoordPointer: function(size, type, stride, pointer) { + GL.immediate.setClientAttribute('T' + GL.immediate.clientActiveTexture, size, type, stride, pointer); + }, + glNormalPointer: function(type, stride, pointer) { + GL.immediate.setClientAttribute('N', 1, type, stride, pointer); }, glColorPointer: function(size, type, stride, pointer) { GL.immediate.setClientAttribute('C', size, type, stride, pointer); }, glClientActiveTexture: function(texture) { - GL.immediate.clientActiveTexture = texture; + GL.immediate.clientActiveTexture = texture - 0x84C0; // GL_TEXTURE0 }, // OpenGL Immediate Mode matrix routines. @@ -1566,27 +1635,23 @@ var LibraryGL = { }, glLoadMatrixd: function(matrix) { - GL.immediate.matrix.lib.mat4.set(GL.immediate.matrix[GL.immediate.currentMatrix], - {{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}); + GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}, GL.immediate.matrix[GL.immediate.currentMatrix]); }, glLoadMatrixf: function(matrix) { #if GL_DEBUG console.log('glLoadMatrixf receiving: ' + Array.prototype.slice.call(HEAPF32.subarray(matrix >> 2, (matrix >> 2) + 16))); #endif - GL.immediate.matrix.lib.mat4.set(GL.immediate.matrix[GL.immediate.currentMatrix], - {{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}); + GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}, GL.immediate.matrix[GL.immediate.currentMatrix]); }, glLoadTransposeMatrixd: function(matrix) { - GL.immediate.matrix.lib.mat4.set(GL.immediate.matrix[GL.immediate.currentMatrix], - {{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}); + GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}, GL.immediate.matrix[GL.immediate.currentMatrix]); GL.immediate.matrix.lib.mat4.transpose(GL.immediate.matrix[GL.immediate.currentMatrix]); }, glLoadTransposeMatrixf: function(matrix) { - GL.immediate.matrix.lib.mat4.set(GL.immediate.matrix[GL.immediate.currentMatrix], - {{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}); + GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}, GL.immediate.matrix[GL.immediate.currentMatrix]); GL.immediate.matrix.lib.mat4.transpose(GL.immediate.matrix[GL.immediate.currentMatrix]); }, @@ -1602,16 +1667,14 @@ var LibraryGL = { glMultTransposeMatrixd: function(matrix) { var colMajor = GL.immediate.matrix.lib.mat4.create(); - GL.immediate.matrix.lib.mat4.set(colMajor, - {{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}); + GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F64', 'matrix', 'matrix+16*8') }}}, colMajor); GL.immediate.matrix.lib.mat4.transpose(colMajor); GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], colMajor); }, glMultTransposeMatrixf: function(matrix) { var colMajor = GL.immediate.matrix.lib.mat4.create(); - GL.immediate.matrix.lib.mat4.set(colMajor, - {{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}); + GL.immediate.matrix.lib.mat4.set({{{ makeHEAPView('F32', 'matrix', 'matrix+16*4') }}}, colMajor); GL.immediate.matrix.lib.mat4.transpose(colMajor); GL.immediate.matrix.lib.mat4.multiply(GL.immediate.matrix[GL.immediate.currentMatrix], colMajor); }, diff --git a/src/library_sdl.js b/src/library_sdl.js index 9e9bf10f..a4923352 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -774,6 +774,10 @@ var LibrarySDL = { // SDL_Image + IMG_Init: function(flags) { + return flags; // We support JPG, PNG, TIF because browsers do + }, + IMG_Load__deps: ['SDL_LockSurface'], IMG_Load: function(filename) { filename = FS.standardizePath(Pointer_stringify(filename)); diff --git a/system/include/libc/sys/types.h b/system/include/libc/sys/types.h index 77acc92e..2f887537 100644 --- a/system/include/libc/sys/types.h +++ b/system/include/libc/sys/types.h @@ -140,12 +140,8 @@ typedef unsigned long vm_size_t; #define __BIT_TYPES_DEFINED__ -// XXX Emscripten: removed unsigned types which are already defined -typedef signed char int8_t; -typedef short int16_t; -typedef int int32_t; -typedef long long int64_t; -typedef int32_t register_t; +// XXX Emscripten: removed types which are already defined, get them from stdint +#include <stdint.h> #endif /* __MS_types__ */ /* diff --git a/tests/cubegeom.c b/tests/cubegeom.c index 1fb5eeef..529e1355 100644 --- a/tests/cubegeom.c +++ b/tests/cubegeom.c @@ -87,15 +87,15 @@ int main(int argc, char *argv[]) glLoadIdentity(); // original: glFrustum(-0.6435469817188064, 0.6435469817188064 ,-0.48266022190470925, 0.48266022190470925 ,0.5400000214576721, 2048); glFrustum(-0.6435469817188064, 0.1435469817188064 ,-0.48266022190470925, 0.88266022190470925 ,0.5400000214576721, 2048); + //GLfloat pm[] = { 1.372136116027832, 0, 0, 0, 0, 0.7910231351852417, 0, 0, -0.6352481842041016, 0.29297152161598206, -1.0005275011062622, -1, 0, 0, -1.080284833908081, 0 }; + //glLoadMatrixf(pm); + glMatrixMode(GL_MODELVIEW); GLfloat matrixData[] = { -1, 0, 0, 0, 0, 0,-1, 0, 0, 1, 0, 0, 0, 0, 0, 1 }; glLoadMatrixf(matrixData); - glRotated(0, 0, 1, 0); - glRotated(0,-1, 0, 0); - glRotated(0, 0, 0,-1); //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown glEnable(GL_CULL_FACE); @@ -186,7 +186,7 @@ int main(int argc, char *argv[]) // sauer vertex data is apparently 0-12: V3F, 12: N1B, 16-24: T2F, 24-28: T2S, 28-32: C4B glVertexPointer(3, GL_FLOAT, 32, (void*)0); // all these apply to the ARRAY_BUFFER that is bound glTexCoordPointer(2, GL_FLOAT, 32, (void*)16); - glClientActiveTexture(GL_TEXTURE1); + glClientActiveTexture(GL_TEXTURE1); // XXX seems to be ignored in native build glTexCoordPointer(2, GL_SHORT, 32, (void*)24); glClientActiveTexture(GL_TEXTURE0); // likely not needed, it is a cleanup glNormalPointer(GL_BYTE, 32, (void*)12); @@ -204,8 +204,8 @@ int main(int argc, char *argv[]) "void main(void)\n" "{\n" " gl_Position = ftransform();\n" - " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/100 + texgenscroll.xy;\n" // added /100 here - " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100 * 3.051851e-05;\n" + " gl_TexCoord[0].xy = gl_MultiTexCoord0.xy/100.0 + texgenscroll.xy;\n" // added /100 here + " gl_TexCoord[1].xy = gl_MultiTexCoord1.xy/100.0 * 3.051851e-05;\n" "}\n"; const char *fragmentShader = "uniform vec4 colorparams;\n" "uniform sampler2D diffusemap, lightmap;\n" diff --git a/tests/gl_ps.c b/tests/gl_ps.c new file mode 100644 index 00000000..c4ec7675 --- /dev/null +++ b/tests/gl_ps.c @@ -0,0 +1,217 @@ +/******************************************************************* + * * + * 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 + GLfloat vertexData[] = { 0, 0, 10, 10, // texture2, position2 + 1, 0, 300, 10, + 1, 1, 300, 128, + 0, 1, 10, 128, + 0, 0.5, 410, 10, + 1, 0.5, 600, 10, + 1, 1, 630, 200, + 0.5, 1, 310, 250, + 0, 0, 100, 300, + 1, 0, 300, 300, + 1, 1, 300, 400, + 0, 1, 100, 400 }; + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 4*4, &vertexData[0]); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 4*4, &vertexData[2]); + + 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.png b/tests/gl_ps.png Binary files differnew file mode 100644 index 00000000..185f7166 --- /dev/null +++ b/tests/gl_ps.png diff --git a/tests/runner.py b/tests/runner.py index 0e1b4716..1d4b827c 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7224,8 +7224,13 @@ elif 'browser' in str(sys.argv): def test_sdlglshader(self): self.btest('sdlglshader.c', reference='sdlglshader.png') + def test_gl_ps(self): + # pointers and a shader + shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) + self.btest('gl_ps.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png', '-s', 'GL_DEBUG=1']) + def zzztest_cubegeom(self): - self.btest('cubegeom.c', reference='sdlglshader.png') + self.btest('cubegeom.c', reference='sdlglshader.png', args=['-s', 'GL_DEBUG=1']) elif 'benchmark' in str(sys.argv): # Benchmarks. Run them with argument |benchmark|. To run a specific test, do diff --git a/tests/sdl_ogl_p.c b/tests/sdl_ogl_p.c index 3978f66c..949aaa44 100644 --- a/tests/sdl_ogl_p.c +++ b/tests/sdl_ogl_p.c @@ -58,10 +58,12 @@ int main(int argc, char *argv[]) glViewport( 0, 0, 640, 480 ); glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); + 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 - glOrtho( 0, 640, 480, 0, -1, 1 ); - glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); diff --git a/tools/shared.py b/tools/shared.py index 5751ef60..010351ee 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -216,7 +216,17 @@ try: except NameError: pass -WINDOWS = sys.platform.startswith ('win') +WINDOWS = sys.platform.startswith('win') + +# If we have 'env', we should use that to find python, because |python| may fail while |env python| may work +# (For example, if system python is 3.x while we need 2.x, and env gives 2.x if told to do so.) +ENV_PREFIX = [] +if not WINDOWS: + try: + assert 'Python' in Popen(['env', 'python', '-V'], stdout=PIPE, stderr=STDOUT).communicate()[0] + ENV_PREFIX = ['env'] + except: + pass # Temp file utilities @@ -600,13 +610,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e if output_filename is None: output_filename = filename + '.o' try_delete(output_filename) - Popen(['python', EMCC, filename] + args + ['-o', output_filename], stdout=stdout, stderr=stderr, env=env).communicate() + Popen(ENV_PREFIX + ['python', EMCC, filename] + args + ['-o', output_filename], stdout=stdout, stderr=stderr, env=env).communicate() assert os.path.exists(output_filename), 'emcc could not create output file' @staticmethod def emar(action, output_filename, filenames, stdout=None, stderr=None, env=None): try_delete(output_filename) - Popen(['python', EMAR, action, output_filename] + filenames, stdout=stdout, stderr=stderr, env=env).communicate() + Popen(ENV_PREFIX + ['python', EMAR, action, output_filename] + filenames, stdout=stdout, stderr=stderr, env=env).communicate() if 'c' in action: assert os.path.exists(output_filename), 'emar could not create output file' @@ -617,7 +627,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e # Run Emscripten settings = Settings.serialize() - compiler_output = timeout_run(Popen(['python', EMSCRIPTEN, filename + ('.o.ll' if append_ext else ''), '-o', filename + '.o.js'] + settings + extra_args, stdout=PIPE), None, 'Compiling') + compiler_output = timeout_run(Popen(ENV_PREFIX + ['python', EMSCRIPTEN, filename + ('.o.ll' if append_ext else ''), '-o', filename + '.o.js'] + settings + extra_args, stdout=PIPE), None, 'Compiling') #print compiler_output # Detect compilation crashes and errors |