diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-02-25 19:23:56 -0500 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-02-25 19:23:56 -0500 |
commit | 230c0e80dfcd44870bec3254c399db430f6e1d98 (patch) | |
tree | 745ec3b082adc222050b4d48a416d7a969dd148d /tests | |
parent | 5a99d2567e76f257309cfd225876f3a5402e5f46 (diff) | |
parent | 9d4ef477a511ae4136c2d63e0150a4768cbd53ea (diff) |
Merge branch 'incoming'
Conflicts:
AUTHORS
Diffstat (limited to 'tests')
35 files changed, 4265 insertions, 108 deletions
diff --git a/tests/aniso.png b/tests/aniso.png Binary files differindex 5f5812d2..2bcb2f5f 100644 --- a/tests/aniso.png +++ b/tests/aniso.png diff --git a/tests/cubegeom.c b/tests/cubegeom.c index c137ad80..6158b124 100644 --- a/tests/cubegeom.c +++ b/tests/cubegeom.c @@ -207,6 +207,20 @@ int main(int argc, char *argv[]) glNormalPointer(GL_BYTE, 32, (void*)12); glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28); + int temp; // test glGetPointerv, glGetIntegerv + glGetPointerv(GL_VERTEX_ARRAY_POINTER, &temp); assert(temp == 0); + glGetPointerv(GL_COLOR_ARRAY_POINTER, &temp); assert(temp == 28); + glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &temp); assert(temp == 16); + glGetIntegerv(GL_VERTEX_ARRAY_SIZE, &temp); assert(temp == 3); + glGetIntegerv(GL_VERTEX_ARRAY_TYPE, &temp); assert(temp == GL_FLOAT); + glGetIntegerv(GL_VERTEX_ARRAY_STRIDE, &temp); assert(temp == 32); + glGetIntegerv(GL_COLOR_ARRAY_SIZE, &temp); assert(temp == 4); + glGetIntegerv(GL_COLOR_ARRAY_TYPE, &temp); assert(temp == GL_UNSIGNED_BYTE); + glGetIntegerv(GL_COLOR_ARRAY_STRIDE, &temp); assert(temp == 32); + glGetIntegerv(GL_TEXTURE_COORD_ARRAY_SIZE, &temp); assert(temp == 2); + glGetIntegerv(GL_TEXTURE_COORD_ARRAY_TYPE, &temp); assert(temp == GL_FLOAT); + glGetIntegerv(GL_TEXTURE_COORD_ARRAY_STRIDE, &temp); assert(temp == 32); + glBindTexture(GL_TEXTURE_2D, texture); // diffuse? glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE1); diff --git a/tests/cubegeom_pre2_vao.c b/tests/cubegeom_pre2_vao.c new file mode 100644 index 00000000..98bedd54 --- /dev/null +++ b/tests/cubegeom_pre2_vao.c @@ -0,0 +1,380 @@ +/* +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" +#if !USE_GLEW +#include "SDL/SDL_opengl.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +PFNGLGENVERTEXARRAYSPROC glGenVertexArrays_ = NULL; +PFNGLBINDVERTEXARRAYPROC glBindVertexArray_ = NULL; +PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays_ = NULL; + +void verify() { + int width = 640, height = 480; + unsigned char *data = (unsigned char*)malloc(width*height*4); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + int sum = 0; + for (int x = 0; x < width*height*4; x++) { + if (x % 4 != 3) sum += x * data[x]; + } +#if EMSCRIPTEN + int result = sum; + REPORT_RESULT(); +#endif +} + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + 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 ); + screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL ); + if ( !screen ) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + glClearColor( 0, 0, 0, 0 ); + glClear( GL_COLOR_BUFFER_BIT ); + + glGenVertexArrays_ = (PFNGLGENVERTEXARRAYSPROC) SDL_GL_GetProcAddress("glGenVertexArrays"); + assert(glGenVertexArrays_); + glBindVertexArray_ = (PFNGLBINDVERTEXARRAYPROC) SDL_GL_GetProcAddress("glBindVertexArray"); + assert(glBindVertexArray_); + glDeleteVertexArrays_ = (PFNGLDELETEVERTEXARRAYSPROC) SDL_GL_GetProcAddress("glDeleteVertexArrays"); + assert(glDeleteVertexArrays_); + + // Generate a VAO + GLuint vao; + glGenVertexArrays_(1, &vao); + glBindVertexArray_(vao); + + // Create a texture + + GLuint texture; + glGenTextures( 1, &texture ); + glBindTexture( GL_TEXTURE_2D, texture ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + GLubyte textureData[16*16*4]; + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8); + } + } + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, + GL_RGBA, GL_UNSIGNED_BYTE, textureData ); + + // Create a second texture + + GLuint texture2; + glGenTextures( 1, &texture2 ); + glBindTexture( GL_TEXTURE_2D, texture2 ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + GLubyte texture2Data[] = { 0xff, 0, 0, 0xff, + 0, 0xff, 0, 0xaa, + 0, 0, 0xff, 0x55, + 0x80, 0x90, 0x70, 0 }; + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texture2Data ); + + // BEGIN + +#if USE_GLEW + glewInit(); +#endif + + glMatrixMode(GL_PROJECTION); + 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); + //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown + +// glEnable(GL_CULL_FACE); + // glEnable(GL_DEPTH_TEST); + + //glClear(GL_DEPTH_BUFFER_BIT); + +// glEnableClientState(GL_NORMAL_ARRAY); + // glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + glActiveTexture(GL_TEXTURE0); + + glEnableClientState(GL_VERTEX_ARRAY); + + GLuint arrayBuffer, elementBuffer; + glGenBuffers(1, &arrayBuffer); + glGenBuffers(1, &elementBuffer); + + GLubyte arrayData[] = { +/* +[0, 0, 0, 67] ==> 128 float +[0, 0, 128, 67] ==> 256 float +[0, 0, 0, 68] ==> 512 float +[0, 0, 128, 68] ==> 1024 float + +[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0 + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2 + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3 + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4 + 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5 + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7 + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9 + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10 + 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12 + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13 + 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14 + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15 + + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128 + }; + assert(sizeof(arrayData) == 1408); + glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 }; + assert(sizeof(elementData) == 48); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + + // 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); // 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); +// glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28); + + glBindTexture(GL_TEXTURE_2D, texture); // diffuse? + glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, texture2); // lightmap? + glActiveTexture(GL_TEXTURE0); + + GLint ok; + + const char *vertexShader = "uniform mat4 u_modelView;\n" + "uniform mat4 u_projection;\n" + "varying vec4 v_texCoord0;\n" + "void main(void)\n" + "{\n" // (gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex) + // (u_projection * u_modelView * a_position) + " gl_Position = (u_projection * u_modelView * gl_Vertex) + vec4(200, 0, 0, 0);\n" + " v_texCoord0.xy = gl_MultiTexCoord0.xy/20.0;\n" // added /100 here + "}\n"; + const char *fragmentShader = "uniform sampler2D diffusemap;\n" + "varying vec4 v_texCoord0;\n" + "void main(void)\n" + "{\n" + " vec4 diffuse = texture2D(diffusemap, v_texCoord0.xy);\n" + " gl_FragColor = diffuse;\n" + "}\n"; + + GLuint vs = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vs, 1, &vertexShader, NULL); + glCompileShader(vs); + glGetShaderiv(vs, GL_COMPILE_STATUS, &ok); + if (!ok) { + printf("Shader compilation error with vertex\n"); + GLint infoLen = 0; + glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char *)malloc(sizeof(char) * infoLen+1); + glGetShaderInfoLog(vs, infoLen, NULL, infoLog); + printf("Error compiling shader:\n%s\n", infoLog); + } + } + + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fs, 1, &fragmentShader, NULL); + glCompileShader(fs); + glGetShaderiv(fs, GL_COMPILE_STATUS, &ok); + if (!ok) { + printf("Shader compilation error with fragment\n"); + GLint infoLen = 0; + glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char *)malloc(sizeof(char) * infoLen+1); + glGetShaderInfoLog(vs, infoLen, NULL, infoLog); + printf("Error compiling shader:\n%s\n", infoLog); + } + } + + GLuint program = glCreateProgram(); + + glAttachShader(program, vs); + glAttachShader(program, fs); + glLinkProgram(program); + glGetProgramiv(program, GL_LINK_STATUS, &ok); + assert(ok); + + glUseProgram(program); + + //GLint lightmapLocation = glGetUniformLocation(program, "lightmap"); + //assert(lightmapLocation >= 0); + //glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit? + + GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap"); + assert(diffusemapLocation >= 0); + glUniform1i(diffusemapLocation, 0); + + //GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll"); + //assert(texgenscrollLocation >= 0); + + //GLint colorparamsLocation = glGetUniformLocation(program, "colorparams"); + //assert(colorparamsLocation >= 0); + + //GLfloat texgenscrollData[] = { 0, 0, 0, 0 }; + //glUniform4fv(texgenscrollLocation, 1, texgenscrollData); + + //GLfloat colorparamsData[] = { 2, 2, 2, 1 }; + //glUniform4fv(colorparamsLocation, 1, colorparamsData); + + { + GLfloat data[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, data); + printf("Modelview: "); + for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]); + printf("\n"); + //memset(data, 0, 16*4); + GLint modelViewLocation = glGetUniformLocation(program, "u_modelView"); + assert(modelViewLocation >= 0); + glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, data); + } + { + GLfloat data[16]; + glGetFloatv(GL_PROJECTION_MATRIX, data); + printf("Projection: "); + for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]); + printf("\n"); + //memset(data, 0, 16*4); + GLint projectionLocation = glGetUniformLocation(program, "u_projection"); + assert(projectionLocation >= 0); + glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, data); + } + +/* + glBindAttribLocation(program, 0, "a_position"); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 32, (void*)0); + glEnableVertexAttribArray(0); + + glBindAttribLocation(program, 1, "v_texCoord0"); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 32, (void*)16); + glEnableVertexAttribArray(1); +*/ + + // stop recording in the VAO + + glBindVertexArray_(0); + + // unbind all the stuff the VAO would save for us, so this is a valid test + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + // draw with VAO + + glBindVertexArray_(vao); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36); + + // END + + SDL_GL_SwapBuffers(); + + verify(); + +#if !EMSCRIPTEN + SDL_Delay(1500); +#endif + + // SDL_Quit(); + + return 0; +} + diff --git a/tests/cubegeom_pre2_vao2.c b/tests/cubegeom_pre2_vao2.c new file mode 100644 index 00000000..e3ab4d62 --- /dev/null +++ b/tests/cubegeom_pre2_vao2.c @@ -0,0 +1,381 @@ +/* +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" +#if !USE_GLEW +#include "SDL/SDL_opengl.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +PFNGLGENVERTEXARRAYSPROC glGenVertexArrays_ = NULL; +PFNGLBINDVERTEXARRAYPROC glBindVertexArray_ = NULL; +PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays_ = NULL; + +void verify() { + int width = 640, height = 480; + unsigned char *data = (unsigned char*)malloc(width*height*4); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + int sum = 0; + for (int x = 0; x < width*height*4; x++) { + if (x % 4 != 3) sum += x * data[x]; + } +#if EMSCRIPTEN + int result = sum; + REPORT_RESULT(); +#endif +} + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + 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 ); + screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL ); + if ( !screen ) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + glClearColor( 0, 0, 0, 0 ); + glClear( GL_COLOR_BUFFER_BIT ); + + glGenVertexArrays_ = (PFNGLGENVERTEXARRAYSPROC) SDL_GL_GetProcAddress("glGenVertexArrays"); + assert(glGenVertexArrays_); + glBindVertexArray_ = (PFNGLBINDVERTEXARRAYPROC) SDL_GL_GetProcAddress("glBindVertexArray"); + assert(glBindVertexArray_); + glDeleteVertexArrays_ = (PFNGLDELETEVERTEXARRAYSPROC) SDL_GL_GetProcAddress("glDeleteVertexArrays"); + assert(glDeleteVertexArrays_); + + glEnableClientState(GL_TEXTURE_COORD_ARRAY); // enabling it *before* the vao does nothing, the vao should wipe it out! + + // Generate a VAO + GLuint vao; + glGenVertexArrays_(1, &vao); + glBindVertexArray_(vao); + + // Create a texture + + GLuint texture; + glGenTextures( 1, &texture ); + glBindTexture( GL_TEXTURE_2D, texture ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + GLubyte textureData[16*16*4]; + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8); + } + } + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, + GL_RGBA, GL_UNSIGNED_BYTE, textureData ); + + // Create a second texture + + GLuint texture2; + glGenTextures( 1, &texture2 ); + glBindTexture( GL_TEXTURE_2D, texture2 ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + GLubyte texture2Data[] = { 0xff, 0, 0, 0xff, + 0, 0xff, 0, 0xaa, + 0, 0, 0xff, 0x55, + 0x80, 0x90, 0x70, 0 }; + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texture2Data ); + + // BEGIN + +#if USE_GLEW + glewInit(); +#endif + + glMatrixMode(GL_PROJECTION); + 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); + //glTranslated(-512,-512,-527); // XXX this should be uncommented, but if it is then nothing is shown + +// glEnable(GL_CULL_FACE); + // glEnable(GL_DEPTH_TEST); + + //glClear(GL_DEPTH_BUFFER_BIT); + +// glEnableClientState(GL_NORMAL_ARRAY); + // glEnableClientState(GL_COLOR_ARRAY); + + glActiveTexture(GL_TEXTURE0); + + glEnableClientState(GL_VERTEX_ARRAY); + + GLuint arrayBuffer, elementBuffer; + glGenBuffers(1, &arrayBuffer); + glGenBuffers(1, &elementBuffer); + + GLubyte arrayData[] = { +/* +[0, 0, 0, 67] ==> 128 float +[0, 0, 128, 67] ==> 256 float +[0, 0, 0, 68] ==> 512 float +[0, 0, 128, 68] ==> 1024 float + +[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0 + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2 + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3 + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4 + 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5 + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7 + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9 + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10 + 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12 + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13 + 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14 + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15 + + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128 + }; + assert(sizeof(arrayData) == 1408); + glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 }; + assert(sizeof(elementData) == 48); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + + // 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); // 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); +// glColorPointer(4, GL_UNSIGNED_BYTE, 32, (void*)28); + + glBindTexture(GL_TEXTURE_2D, texture); // diffuse? + glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, texture2); // lightmap? + glActiveTexture(GL_TEXTURE0); + + GLint ok; + + const char *vertexShader = "uniform mat4 u_modelView;\n" + "uniform mat4 u_projection;\n" + "varying vec4 v_texCoord0;\n" + "void main(void)\n" + "{\n" // (gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex) + // (u_projection * u_modelView * a_position) + " gl_Position = (u_projection * u_modelView * gl_Vertex) + vec4(200, 0, 0, 0);\n" + " v_texCoord0.xy = gl_MultiTexCoord0.xy/20.0;\n" // added /100 here + "}\n"; + const char *fragmentShader = "uniform sampler2D diffusemap;\n" + "varying vec4 v_texCoord0;\n" + "void main(void)\n" + "{\n" + " vec4 diffuse = texture2D(diffusemap, v_texCoord0.xy);\n" + " gl_FragColor = diffuse;\n" + "}\n"; + + GLuint vs = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vs, 1, &vertexShader, NULL); + glCompileShader(vs); + glGetShaderiv(vs, GL_COMPILE_STATUS, &ok); + if (!ok) { + printf("Shader compilation error with vertex\n"); + GLint infoLen = 0; + glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char *)malloc(sizeof(char) * infoLen+1); + glGetShaderInfoLog(vs, infoLen, NULL, infoLog); + printf("Error compiling shader:\n%s\n", infoLog); + } + } + + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fs, 1, &fragmentShader, NULL); + glCompileShader(fs); + glGetShaderiv(fs, GL_COMPILE_STATUS, &ok); + if (!ok) { + printf("Shader compilation error with fragment\n"); + GLint infoLen = 0; + glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char *)malloc(sizeof(char) * infoLen+1); + glGetShaderInfoLog(vs, infoLen, NULL, infoLog); + printf("Error compiling shader:\n%s\n", infoLog); + } + } + + GLuint program = glCreateProgram(); + + glAttachShader(program, vs); + glAttachShader(program, fs); + glLinkProgram(program); + glGetProgramiv(program, GL_LINK_STATUS, &ok); + assert(ok); + + glUseProgram(program); + + //GLint lightmapLocation = glGetUniformLocation(program, "lightmap"); + //assert(lightmapLocation >= 0); + //glUniform1i(lightmapLocation, 1); // sampler2D? Is it the texture unit? + + GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap"); + assert(diffusemapLocation >= 0); + glUniform1i(diffusemapLocation, 0); + + //GLint texgenscrollLocation = glGetUniformLocation(program, "texgenscroll"); + //assert(texgenscrollLocation >= 0); + + //GLint colorparamsLocation = glGetUniformLocation(program, "colorparams"); + //assert(colorparamsLocation >= 0); + + //GLfloat texgenscrollData[] = { 0, 0, 0, 0 }; + //glUniform4fv(texgenscrollLocation, 1, texgenscrollData); + + //GLfloat colorparamsData[] = { 2, 2, 2, 1 }; + //glUniform4fv(colorparamsLocation, 1, colorparamsData); + + { + GLfloat data[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, data); + printf("Modelview: "); + for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]); + printf("\n"); + //memset(data, 0, 16*4); + GLint modelViewLocation = glGetUniformLocation(program, "u_modelView"); + assert(modelViewLocation >= 0); + glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, data); + } + { + GLfloat data[16]; + glGetFloatv(GL_PROJECTION_MATRIX, data); + printf("Projection: "); + for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]); + printf("\n"); + //memset(data, 0, 16*4); + GLint projectionLocation = glGetUniformLocation(program, "u_projection"); + assert(projectionLocation >= 0); + glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, data); + } + +/* + glBindAttribLocation(program, 0, "a_position"); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 32, (void*)0); + glEnableVertexAttribArray(0); + + glBindAttribLocation(program, 1, "v_texCoord0"); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 32, (void*)16); + glEnableVertexAttribArray(1); +*/ + + // stop recording in the VAO + + glBindVertexArray_(0); + + // unbind all the stuff the VAO would save for us, so this is a valid test + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + + // draw with VAO + + glBindVertexArray_(vao); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36); + + // END + + SDL_GL_SwapBuffers(); + + verify(); + +#if !EMSCRIPTEN + SDL_Delay(1500); +#endif + + // SDL_Quit(); + + return 0; +} + diff --git a/tests/cubegeom_pre_vao.c b/tests/cubegeom_pre_vao.c new file mode 100644 index 00000000..f1d35fb5 --- /dev/null +++ b/tests/cubegeom_pre_vao.c @@ -0,0 +1,333 @@ +/* +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" +#if !USE_GLEW +#include "SDL/SDL_opengl.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <assert.h> + +void verify() { + int width = 640, height = 480; + unsigned char *data = (unsigned char*)malloc(width*height*4); + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + int sum = 0; + for (int x = 0; x < width*height*4; x++) { + if (x % 4 != 3) sum += x * data[x]; + } +#if EMSCRIPTEN + int result = sum; + REPORT_RESULT(); +#endif +} + +int main(int argc, char *argv[]) +{ + SDL_Surface *screen; + 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 ); + screen = SDL_SetVideoMode( 640, 480, 24, SDL_OPENGL ); + if ( !screen ) { + printf("Unable to set video mode: %s\n", SDL_GetError()); + return 1; + } + + glClearColor( 0, 0, 0, 0 ); + glClear( GL_COLOR_BUFFER_BIT ); + + // Create a texture + + GLuint texture; + glGenTextures( 1, &texture ); + glBindTexture( GL_TEXTURE_2D, texture ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + GLubyte textureData[16*16*4]; + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8); + } + } + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, + GL_RGBA, GL_UNSIGNED_BYTE, textureData ); + + // Create a second texture + + GLuint texture2; + glGenTextures( 1, &texture2 ); + glBindTexture( GL_TEXTURE_2D, texture2 ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + GLubyte texture2Data[] = { 0xff, 0, 0, 0xff, + 0, 0xff, 0, 0xaa, + 0, 0, 0xff, 0x55, + 0x80, 0x90, 0x70, 0 }; + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, + GL_RGBA, GL_UNSIGNED_BYTE, texture2Data ); + + // BEGIN + +#if USE_GLEW + glewInit(); +#endif + + glMatrixMode(GL_PROJECTION); + 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); + + glActiveTexture(GL_TEXTURE0); + + GLuint arrayBuffer, elementBuffer; + glGenBuffers(1, &arrayBuffer); + glGenBuffers(1, &elementBuffer); + + GLubyte arrayData[] = { +/* +[0, 0, 0, 67] ==> 128 float +[0, 0, 128, 67] ==> 256 float +[0, 0, 0, 68] ==> 512 float +[0, 0, 128, 68] ==> 1024 float + +[vertex x ] [vertex y ] [vertex z ] [nr] [texture u ] [texture v ] [lm u ] [lm v ] [color r,g,b,a ] */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 0 + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 1 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 2 + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 3 + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 4 + 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, // 5 + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 6 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 7 + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 8 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 9 + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 10 + 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 11 + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 12 + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 0, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 13 + 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 14 + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 67, 0, 0, 128, 67, 0, 0, 0, 0, 128, 128, 128, 128, // 15 + + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 0, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 128, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, + 0, 0, 128, 68, 0, 0, 128, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 128, 128 + }; + + // Generate a VAO + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + assert(sizeof(arrayData) == 1408); + glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(arrayData), arrayData, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + GLushort elementData[] = { 1, 2, 0, 2, 3, 0, 5, 6, 4, 6, 7, 4, 9, 10, 8, 10, 11, 8, 13, 14, 12, 14, 15, 12 }; + assert(sizeof(elementData) == 48); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elementData), elementData, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer); + + glBindTexture(GL_TEXTURE_2D, texture); // diffuse? + glActiveTexture(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, texture2); // lightmap? + glActiveTexture(GL_TEXTURE0); + + GLint ok; + + const char *vertexShader = "attribute vec4 a_position;\n" + "attribute vec4 a_texCoord0;\n" + "uniform mat4 u_modelView;\n" + "uniform mat4 u_projection;\n" + "varying vec4 v_texCoord0;\n" + "void main(void)\n" + "{\n" + " gl_Position = (u_projection * u_modelView * a_position) + vec4(200, 0, 0, 0);\n" + " v_texCoord0.xy = a_texCoord0.xy/20.0;\n" // added /20 here + "}\n"; + const char *fragmentShader = "uniform sampler2D diffusemap;\n" + "varying vec4 v_texCoord0;\n" + "void main(void)\n" + "{\n" + " vec4 diffuse = texture2D(diffusemap, v_texCoord0.xy);\n" + " gl_FragColor = diffuse;\n" + "}\n"; + + GLuint vs = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vs, 1, &vertexShader, NULL); + glCompileShader(vs); + glGetShaderiv(vs, GL_COMPILE_STATUS, &ok); + if (!ok) { + printf("Shader compilation error with vertex\n"); + GLint infoLen = 0; + glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char *)malloc(sizeof(char) * infoLen+1); + glGetShaderInfoLog(vs, infoLen, NULL, infoLog); + printf("Error compiling shader:\n%s\n", infoLog); + } + } + + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fs, 1, &fragmentShader, NULL); + glCompileShader(fs); + glGetShaderiv(fs, GL_COMPILE_STATUS, &ok); + if (!ok) { + printf("Shader compilation error with fragment\n"); + GLint infoLen = 0; + glGetShaderiv (vs, GL_INFO_LOG_LENGTH, &infoLen); + if (infoLen > 1) + { + char* infoLog = (char *)malloc(sizeof(char) * infoLen+1); + glGetShaderInfoLog(vs, infoLen, NULL, infoLog); + printf("Error compiling shader:\n%s\n", infoLog); + } + } + + GLuint program = glCreateProgram(); + + glAttachShader(program, vs); + glAttachShader(program, fs); + glLinkProgram(program); + glGetProgramiv(program, GL_LINK_STATUS, &ok); + assert(ok); + + glUseProgram(program); + + GLint diffusemapLocation = glGetUniformLocation(program, "diffusemap"); + assert(diffusemapLocation >= 0); + glUniform1i(diffusemapLocation, 0); + + { + GLfloat data[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, data); + printf("Modelview: "); + for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]); + printf("\n"); + GLint modelViewLocation = glGetUniformLocation(program, "u_modelView"); + assert(modelViewLocation >= 0); + glUniformMatrix4fv(modelViewLocation, 1, GL_FALSE, data); + } + { + GLfloat data[16]; + glGetFloatv(GL_PROJECTION_MATRIX, data); + printf("Projection: "); + for (int i = 0; i < 16; i++) printf("%.3f, ", data[i]); + printf("\n"); + GLint projectionLocation = glGetUniformLocation(program, "u_projection"); + assert(projectionLocation >= 0); + glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, data); + } + + glBindAttribLocation(program, 0, "a_position"); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 32, (void*)0); + glEnableVertexAttribArray(0); + + glBindAttribLocation(program, 1, "a_texCoord0"); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 32, (void*)16); + glEnableVertexAttribArray(1); + + // stop recording in the VAO + + glBindVertexArray(0); + + // unbind all the stuff the VAO would save for us, so this is a valid test + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + + // draw with VAO + + glBindVertexArray(vao); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)12); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*) 0); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)24); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)36); + + glBindVertexArray(0); + + glDeleteVertexArrays(1, &vao); + + // END + + SDL_GL_SwapBuffers(); + + verify(); + +#if !EMSCRIPTEN + SDL_Delay(1500); +#endif + + SDL_Quit(); + + return 0; +} diff --git a/tests/float_tex.png b/tests/float_tex.png Binary files differindex 8c3c6502..8fc005ff 100644 --- a/tests/float_tex.png +++ b/tests/float_tex.png diff --git a/tests/fuzz/1.c b/tests/fuzz/1.c new file mode 100644 index 00000000..2017fb76 --- /dev/null +++ b/tests/fuzz/1.c @@ -0,0 +1,117 @@ +/* + * This is a RANDOMLY GENERATED PROGRAM. + * + * Generator: csmith 2.2.0 + * Git version: a8697aa + * Options: --no-volatiles --no-math64 --max-block-depth 2 --max-block-size 2 --max-expr-complexity 2 --max-funcs 2 + * Seed: 1880513882 + */ + +#include "csmith.h" + + +static long __undefined; + +/* --- Struct/Union Declarations --- */ +union U0 { + int32_t f0; + int8_t f1; + const int8_t f2; +}; + +/* --- GLOBAL VARIABLES --- */ +static uint32_t g_4 = 9UL; +static int32_t g_6 = 0xB9DD952EL; +static const int32_t *g_5 = &g_6; +static union U0 g_7[3][9][6] = {{{{-8L},{5L},{0x901516EAL},{7L},{7L},{0x901516EAL}},{{0x520EA0C8L},{0x520EA0C8L},{0x0920A6FFL},{0x0021FBB9L},{0x888C5540L},{-8L}},{{0xDC87A9B6L},{0x42B48371L},{8L},{7L},{-8L},{0x0920A6FFL}},{{-1L},{0xDC87A9B6L},{8L},{5L},{0x520EA0C8L},{-8L}},{{-3L},{5L},{0x0920A6FFL},{0x865B49D5L},{0xDC87A9B6L},{0x901516EAL}},{{0x865B49D5L},{0xDC87A9B6L},{0x901516EAL},{0x0021FBB9L},{-1L},{-1L}},{{0x865B49D5L},{0x42B48371L},{0x42B48371L},{0x865B49D5L},{-3L},{0x0920A6FFL}},{{-3L},{0x520EA0C8L},{0x0021FBB9L},{5L},{0x865B49D5L},{-1L}},{{-1L},{5L},{0L},{7L},{0x865B49D5L},{0x901516EAL}}},{{{0xDC87A9B6L},{0x520EA0C8L},{7L},{0x0021FBB9L},{-3L},{-8L}},{{0x520EA0C8L},{0x42B48371L},{5L},{7L},{-1L},{0x0920A6FFL}},{{-8L},{0xDC87A9B6L},{5L},{5L},{0xDC87A9B6L},{-8L}},{{0x888C5540L},{5L},{7L},{0x865B49D5L},{0x520EA0C8L},{0x901516EAL}},{{7L},{0xDC87A9B6L},{0L},{0x0021FBB9L},{-8L},{-1L}},{{7L},{0x42B48371L},{0x0021FBB9L},{0x865B49D5L},{0x888C5540L},{0x0920A6FFL}},{{0x888C5540L},{0x520EA0C8L},{0x42B48371L},{5L},{7L},{-1L}},{{-8L},{5L},{0x901516EAL},{7L},{7L},{0x901516EAL}},{{0x520EA0C8L},{0x520EA0C8L},{0x0920A6FFL},{0x0021FBB9L},{0x888C5540L},{-8L}}},{{{0xDC87A9B6L},{0x42B48371L},{8L},{7L},{-8L},{0x0920A6FFL}},{{-1L},{0xDC87A9B6L},{8L},{5L},{0x520EA0C8L},{-8L}},{{-3L},{5L},{0x0920A6FFL},{0x865B49D5L},{0xDC87A9B6L},{0x901516EAL}},{{0x865B49D5L},{0xDC87A9B6L},{0x901516EAL},{0x0021FBB9L},{-1L},{-1L}},{{0x865B49D5L},{0x42B48371L},{0x42B48371L},{0x865B49D5L},{-3L},{0x0920A6FFL}},{{-3L},{0x520EA0C8L},{0x0021FBB9L},{5L},{0x865B49D5L},{-1L}},{{-1L},{5L},{0L},{7L},{0x865B49D5L},{0x901516EAL}},{{0xDC87A9B6L},{0x520EA0C8L},{7L},{0x0021FBB9L},{-3L},{-8L}},{{0x520EA0C8L},{0x42B48371L},{5L},{7L},{-1L},{0x0920A6FFL}}}}; +static int32_t g_31 = 1L; +static uint32_t g_32 = 4294967289UL; + + +/* --- FORWARD DECLARATIONS --- */ +static uint16_t func_1(void); +static int32_t * func_9(int32_t * p_10, uint16_t p_11); + + +/* --- FUNCTIONS --- */ +/* ------------------------------------------ */ +/* + * reads : g_4 g_5 g_7 g_32 + * writes: g_5 g_32 + */ +static uint16_t func_1(void) +{ /* block id: 0 */ + int32_t l_3 = (-1L); + if (((safe_unary_minus_func_int16_t_s(l_3)) >= g_4)) + { /* block id: 1 */ + int32_t *l_8 = &l_3; + g_5 = g_5; + (*l_8) ^= (g_7[1][3][2] , 0x44688D23L); + } + else + { /* block id: 4 */ + int32_t *l_12 = &l_3; + int32_t **l_13 = &l_12; + (*l_13) = func_9(((*l_13) = l_12), l_3); + } + return l_3; +} + + +/* ------------------------------------------ */ +/* + * reads : g_32 + * writes: g_32 + */ +static int32_t * func_9(int32_t * p_10, uint16_t p_11) +{ /* block id: 6 */ + int32_t *l_14 = &g_6; + int32_t *l_15 = &g_7[1][3][2].f0; + int32_t *l_16 = &g_6; + int32_t *l_17 = &g_6; + int32_t *l_18 = &g_6; + int32_t *l_19 = &g_6; + int32_t *l_20 = &g_6; + int32_t *l_21 = &g_6; + int32_t *l_22 = &g_6; + int32_t *l_23 = &g_7[1][3][2].f0; + int32_t l_24[8] = {0xF9F11119L,0xF9F11119L,0xF9F11119L,0xF9F11119L,0xF9F11119L,0xF9F11119L,0xF9F11119L,0xF9F11119L}; + int32_t *l_25 = &l_24[7]; + int32_t *l_26 = &l_24[2]; + int32_t *l_27 = &l_24[2]; + int32_t *l_28 = &l_24[0]; + int32_t *l_29 = &g_7[1][3][2].f0; + int32_t *l_30[10] = {(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0,(void*)0}; + int i; + ++g_32; + return p_10; +} + + + + +/* ---------------------------------------- */ +int main (int argc, char* argv[]) +{ + int i, j, k; + int print_hash_value = 0; + if (argc == 2 && strcmp(argv[1], "1") == 0) print_hash_value = 1; + platform_main_begin(); + crc32_gentab(); + func_1(); + for (i = 0; i < 3; i++) + { + for (j = 0; j < 1; j++) + { + for (k = 0; k < 1; k++) + { + transparent_crc(g_7[i][j][k].f0, "g_7[i][j][k].f0", print_hash_value); + transparent_crc(g_7[i][j][k].f1, "g_7[i][j][k].f1", print_hash_value); + if (print_hash_value) printf("index = [%d][%d][%d]\n", i, j, k); + } + } + } + platform_main_end(crc32_context ^ 0xFFFFFFFFUL, print_hash_value); + return 0; +} + diff --git a/tests/fuzz/1.c.txt b/tests/fuzz/1.c.txt new file mode 100644 index 00000000..701369f3 --- /dev/null +++ b/tests/fuzz/1.c.txt @@ -0,0 +1 @@ +checksum = 504CCDC diff --git a/tests/fuzz/creduce_tester.py b/tests/fuzz/creduce_tester.py new file mode 100755 index 00000000..c3460e9d --- /dev/null +++ b/tests/fuzz/creduce_tester.py @@ -0,0 +1,53 @@ +#!/usr/bin/python + +''' +Runs csmith, a C fuzzer, and looks for bugs +''' + +import os, sys, difflib +from subprocess import Popen, PIPE, STDOUT + +sys.path += [os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'tools')] +import shared + +filename = sys.argv[1] +print 'testing file', filename + +print '2) Compile natively' +shared.try_delete(filename) +shared.execute([shared.CLANG_CC, '-O2', filename + '.c', '-o', filename] + CSMITH_CFLAGS, stderr=PIPE) +assert os.path.exists(filename) +print '3) Run natively' +try: + correct = shared.timeout_run(Popen([filename], stdout=PIPE, stderr=PIPE), 3) +except Exception, e: + print 'Failed or infinite looping in native, skipping', e + notes['invalid'] += 1 + os.exit(0) # boring + +print '4) Compile JS-ly and compare' + +def try_js(args): + shared.try_delete(filename + '.js') + shared.execute([shared.EMCC, '-O2', '-s', 'ASM_JS=1', '-s', 'PRECISE_I64_MATH=1', '-s', 'PRECISE_I32_MUL=1', filename + '.c', '-o', filename + '.js'] + CSMITH_CFLAGS + args, stderr=PIPE) + assert os.path.exists(filename + '.js') + js = shared.run_js(filename + '.js', stderr=PIPE, engine=engine1) + assert correct == js, ''.join([a.rstrip()+'\n' for a in difflib.unified_diff(correct.split('\n'), js.split('\n'), fromfile='expected', tofile='actual')]) + +# Try normally, then try unaligned because csmith does generate nonportable code that requires x86 alignment +ok = False +normal = True +for args, note in [([], None), (['-s', 'UNALIGNED_MEMORY=1'], 'unaligned')]: + try: + try_js(args) + ok = True + if note: + notes[note] += 1 + break + except Exception, e: + print e + normal = False +if not ok: sys.exit(1) + +sys.exit(0) # boring + diff --git a/tests/fuzz/csmith.h b/tests/fuzz/csmith.h new file mode 100644 index 00000000..f1334a37 --- /dev/null +++ b/tests/fuzz/csmith.h @@ -0,0 +1,130 @@ +/* -*- mode: C -*- + * + * Copyright (c) 2007-2010 The University of Utah + * All rights reserved. + * + * This file is part of `csmith', a random generator of C programs. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RANDOM_RUNTIME_H +#define RANDOM_RUNTIME_H + +#ifdef CSMITH_MINIMAL +#include "csmith_minimal.h" +#else + +/*****************************************************************************/ + +#include <string.h> + +#define __STDC_LIMIT_MACROS +#include "random_inc.h" + +static uint32_t crc32_tab[256]; +static uint32_t crc32_context = 0xFFFFFFFFUL; + +static void +crc32_gentab (void) +{ + uint32_t crc; + const uint32_t poly = 0xEDB88320UL; + int i, j; + + for (i = 0; i < 256; i++) { + crc = i; + for (j = 8; j > 0; j--) { + if (crc & 1) { + crc = (crc >> 1) ^ poly; + } else { + crc >>= 1; + } + } + crc32_tab[i] = crc; + } +} + +static void +crc32_byte (uint8_t b) { + crc32_context = + ((crc32_context >> 8) & 0x00FFFFFF) ^ + crc32_tab[(crc32_context ^ b) & 0xFF]; +} + +#if defined(__SPLAT__) || defined (__COMPCERT__) || defined(NO_LONGLONG) +static void +crc32_8bytes (uint32_t val) +{ + crc32_byte ((val>>0) & 0xff); + crc32_byte ((val>>8) & 0xff); + crc32_byte ((val>>16) & 0xff); + crc32_byte ((val>>24) & 0xff); +} + +static void +transparent_crc (uint32_t val, char* vname, int flag) +{ + crc32_8bytes(val); + if (flag) { + printf("...checksum after hashing %s : %X\n", vname, crc32_context ^ 0xFFFFFFFFU); + } +} +#else +static void +crc32_8bytes (uint64_t val) +{ + crc32_byte ((val>>0) & 0xff); + crc32_byte ((val>>8) & 0xff); + crc32_byte ((val>>16) & 0xff); + crc32_byte ((val>>24) & 0xff); + crc32_byte ((val>>32) & 0xff); + crc32_byte ((val>>40) & 0xff); + crc32_byte ((val>>48) & 0xff); + crc32_byte ((val>>56) & 0xff); +} + +static void +transparent_crc (uint64_t val, char* vname, int flag) +{ + crc32_8bytes(val); + if (flag) { + printf("...checksum after hashing %s : %lX\n", vname, crc32_context ^ 0xFFFFFFFFUL); + } +} +#endif + +/*****************************************************************************/ + +#endif + +#endif /* RANDOM_RUNTIME_H */ + +/* + * Local Variables: + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ + +/* End of file. */ diff --git a/tests/fuzz/csmith_driver.py b/tests/fuzz/csmith_driver.py new file mode 100755 index 00000000..1cb85451 --- /dev/null +++ b/tests/fuzz/csmith_driver.py @@ -0,0 +1,100 @@ +#!/usr/bin/python + +''' +Runs csmith, a C fuzzer, and looks for bugs +''' + +import os, sys, difflib +from subprocess import Popen, PIPE, STDOUT + +sys.path += [os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'tools')] +import shared + +engine1 = eval('shared.' + sys.argv[1]) if len(sys.argv) > 1 else shared.JS_ENGINES[0] +engine2 = eval('shared.' + sys.argv[2]) if len(sys.argv) > 2 else None + +print 'testing js engines', engine1, engine2 + +CSMITH = os.path.expanduser('~/Dev/csmith/src/csmith') +CSMITH_CFLAGS = ['-I' + os.path.expanduser('~/Dev/csmith/runtime/')] + +filename = os.path.join(shared.CANONICAL_TEMP_DIR, 'fuzzcode') + +shared.DEFAULT_TIMEOUT = 1 + +tried = 0 + +notes = { 'invalid': 0, 'unaligned': 0, 'embug': 0 } + +while 1: + print 'Tried %d, notes: %s' % (tried, notes) + tried += 1 + print '1) Generate C' + shared.execute([CSMITH, '--no-volatiles', '--no-math64'], stdout=open(filename + '.c', 'w')) + + print '2) Compile natively' + shared.try_delete(filename) + shared.execute([shared.CLANG_CC, '-O2', filename + '.c', '-o', filename] + CSMITH_CFLAGS, stderr=PIPE) + assert os.path.exists(filename) + print '3) Run natively' + try: + correct = shared.timeout_run(Popen([filename], stdout=PIPE, stderr=PIPE), 3) + except Exception, e: + print 'Failed or infinite looping in native, skipping', e + notes['invalid'] += 1 + continue + + print '4) Compile JS-ly and compare' + + def try_js(args): + shared.try_delete(filename + '.js') + shared.execute([shared.EMCC, '-O2', '-s', 'ASM_JS=1', '-s', 'PRECISE_I64_MATH=1', '-s', 'PRECISE_I32_MUL=1', filename + '.c', '-o', filename + '.js'] + CSMITH_CFLAGS + args, stderr=PIPE) + assert os.path.exists(filename + '.js') + js = shared.run_js(filename + '.js', stderr=PIPE, engine=engine1, check_timeout=True) + assert correct == js, ''.join([a.rstrip()+'\n' for a in difflib.unified_diff(correct.split('\n'), js.split('\n'), fromfile='expected', tofile='actual')]) + + # Try normally, then try unaligned because csmith does generate nonportable code that requires x86 alignment + ok = False + normal = True + for args, note in [([], None), (['-s', 'UNALIGNED_MEMORY=1'], 'unaligned')]: + try: + try_js(args) + ok = True + if note: + notes[note] += 1 + break + except Exception, e: + print e + normal = False + if not ok: + print "EMSCRIPTEN BUG" + notes['embug'] += 1 + continue #break + #if not ok: + # try: # finally, try with safe heap. if that is triggered, this is nonportable code almost certainly + # try_js(['-s', 'SAFE_HEAP=1']) + # except Exception, e: + # print e + # js = shared.run_js(filename + '.js', stderr=PIPE, full_output=True) + # print js + # if 'SAFE_HEAP' in js: + # notes['safeheap'] += 1 + # else: + # break + + # This is ok. Try in secondary JS engine too + if engine2 and normal: + try: + js2 = shared.run_js(filename + '.js', stderr=PIPE, engine=engine2, full_output=True, check_timeout=True) + except: + print 'failed to run in secondary', js2 + break + + # asm.js testing + assert 'warning: Successfully compiled asm.js code' in js2, 'must validate' + js2 = js2.replace('\nwarning: Successfully compiled asm.js code\n', '') + + assert js2 == correct, ''.join([a.rstrip()+'\n' for a in difflib.unified_diff(correct.split('\n'), js2.split('\n'), fromfile='expected', tofile='actual')]) + 'ODIN FAIL' + print 'odin ok' + + diff --git a/tests/fuzz/platform_generic.h b/tests/fuzz/platform_generic.h new file mode 100644 index 00000000..b2ef33a3 --- /dev/null +++ b/tests/fuzz/platform_generic.h @@ -0,0 +1,132 @@ +/* -*- mode: C -*- + * + * + * Copyright (c) 2007, 2008 The University of Utah + * All rights reserved. + * + * This file is part of `csmith', a random generator of C programs. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PLATFORM_GENERIC_H +#define PLATFORM_GENERIC_H + +/*****************************************************************************/ + +#ifdef STANDALONE +extern int printf (const char *, ...); +#else +#include <stdio.h> +#endif + +static void +platform_main_begin(void) +{ + /* Nothing to do. */ +} + +static void +platform_main_end(uint32_t crc, int flag) +{ +#if defined (__FRAMAC) + Frama_C_dump_assert_each(); +#endif + printf ("checksum = %X\n", crc); +#if defined (LOG_WRAPPERS) + { + int i, first; + + printf ("executed wrappers: "); + first = 1; + for (i=1; i<N_WRAP+1; i++) { + if (__executed_checks[i]) { + if (!first) { + printf (","); + } else { + first = 0; + } + printf ("%d", i); + } + } + printf ("\n"); + + printf ("dead wrappers: "); + first = 1; + for (i=1; i<N_WRAP+1; i++) { + if (!__executed_checks[i]) { + if (!first) { + printf (","); + } else { + first = 0; + } + printf ("%d", i); + } + } + printf ("\n"); + + printf ("wrappers that failed at least once: "); + first = 1; + for (i=1; i<N_WRAP+1; i++) { + if (__failed_checks[i]) { + if (!first) { + printf (","); + } else { + first = 0; + } + printf ("%d", i); + } + } + printf ("\n"); + + printf ("wrappers that never failed (or never executed): "); + first = 1; + for (i=1; i<N_WRAP+1; i++) { + if (!__failed_checks[i]) { + if (!first) { + printf (","); + } else { + first = 0; + } + printf ("%d", i); + } + } + printf ("\n"); + } +#endif +} + +#define MB (1<<20) + +/*****************************************************************************/ + +#endif /* PLATFORM_GENERIC_H */ + +/* + * Local Variables: + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ + +/* End of file. */ diff --git a/tests/fuzz/random_inc.h b/tests/fuzz/random_inc.h new file mode 100644 index 00000000..7559cbd7 --- /dev/null +++ b/tests/fuzz/random_inc.h @@ -0,0 +1,129 @@ +/* -*- mode: C -*- + * + * Copyright (c) 2007-2010 The University of Utah + * All rights reserved. + * + * This file is part of `csmith', a random generator of C programs. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RANDOM_INC_H +#define RANDOM_INC_H + + +#if defined(STANDALONE) + #if defined(_MSC_VER) + #include <limits.h> + #include "windows/stdint.h" + #elif defined (IA32_ARCH) + #include "stdint_ia32.h" + #elif defined (IA64_ARCH) + #include "stdint_ia64.h" + #elif defined (MSP430) + #include "stdint_msp430.h" + #elif defined (AVR_ARCH) + #include "stdint_avr.h" + #else + #include "stdint_ia32.h" + #endif +#else + #include <limits.h> + #if defined(_MSC_VER) + #include "windows/stdint.h" + #else + #include <stdint.h> + #endif +#endif + +#include <assert.h> + +/*****************************************************************************/ + +#ifndef DEPUTY +#define COUNT(n) +#define TC +#define SAFE +#endif + +/*****************************************************************************/ + +#ifdef LOG_WRAPPERS +#include "wrapper.h" +char __failed_checks[N_WRAP+1]; +char __executed_checks[N_WRAP+1]; +#define UNDEFINED(__val) (__failed_checks[index]=1,(__val)) +#define LOG_INDEX , int index +#define LOG_EXEC __executed_checks[index]=1; +#else +#define UNDEFINED(__val) (__val) +#define LOG_INDEX +#define LOG_EXEC +#endif + +#if defined(AVR_ARCH) +#include "platform_avr.h" +#elif defined (MSP430) +#include "platform_msp430.h" +#else +#include "platform_generic.h" +#endif + +#define STATIC static + +#if defined (USE_MATH_MACROS_NOTMP) +#include "safe_math_macros_notmp.h" +#elif defined (USE_MATH_MACROS) +#include "safe_math_macros.h" +#else +#define FUNC_NAME(x) (safe_##x) +#include "safe_math.h" +#undef FUNC_NAME +#endif + +#define INT_BIT (sizeof(int)*CHAR_BIT) +#define _CSMITH_BITFIELD(x) (((x)>INT_BIT)?((x)%INT_BIT):(x)) + +#ifdef TCC + +void* memcpy(void* dest, const void* src, size_t count) { + char* dst8 = (char*)dest; + char* src8 = (char*)src; + + while (count--) { + *dst8++ = *src8++; + } + return dest; +} + +void *memset(void *s, int c, size_t n) +{ + unsigned char* p=s; + while(n--) + *p++ = (unsigned char)c; + return s; +} + +#endif + +#endif // RANDOM_INC_H diff --git a/tests/fuzz/safe_math.h b/tests/fuzz/safe_math.h new file mode 100644 index 00000000..393ebba1 --- /dev/null +++ b/tests/fuzz/safe_math.h @@ -0,0 +1,947 @@ + +#ifndef SAFE_MATH_H +#define SAFE_MATH_H + + + + + + + + + +STATIC int8_t +FUNC_NAME(unary_minus_func_int8_t_s)(int8_t si LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT8_MAX>=INT_MAX) + (si==INT8_MIN) ? + (UNDEFINED(si)) : +#endif +#endif + -si; +} + +STATIC int8_t +FUNC_NAME(add_func_int8_t_s_s)(int8_t si1, int8_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT8_MAX>=INT_MAX) + (((si1>0) && (si2>0) && (si1 > (INT8_MAX-si2))) || ((si1<0) && (si2<0) && (si1 < (INT8_MIN-si2)))) ? + (UNDEFINED(si1)) : +#endif +#endif + (si1 + si2); +} + +STATIC int8_t +FUNC_NAME(sub_func_int8_t_s_s)(int8_t si1, int8_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT8_MAX>=INT_MAX) + (((si1^si2) & (((si1 ^ ((si1^si2) & (~INT8_MAX)))-si2)^si2)) < 0) ? + (UNDEFINED(si1)) : +#endif +#endif + (si1 - si2); +} + +STATIC int8_t +FUNC_NAME(mul_func_int8_t_s_s)(int8_t si1, int8_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT8_MAX>=INT_MAX) + (((si1 > 0) && (si2 > 0) && (si1 > (INT8_MAX / si2))) || ((si1 > 0) && (si2 <= 0) && (si2 < (INT8_MIN / si1))) || ((si1 <= 0) && (si2 > 0) && (si1 < (INT8_MIN / si2))) || ((si1 <= 0) && (si2 <= 0) && (si1 != 0) && (si2 < (INT8_MAX / si1)))) ? + (UNDEFINED(si1)) : +#endif +#endif + si1 * si2; +} + +STATIC int8_t +FUNC_NAME(mod_func_int8_t_s_s)(int8_t si1, int8_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((si2 == 0) || ((si1 == INT8_MIN) && (si2 == (-1)))) ? + (UNDEFINED(si1)) : +#endif + (si1 % si2); +} + +STATIC int8_t +FUNC_NAME(div_func_int8_t_s_s)(int8_t si1, int8_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((si2 == 0) || ((si1 == INT8_MIN) && (si2 == (-1)))) ? + (UNDEFINED(si1)) : +#endif + (si1 / si2); +} + +STATIC int8_t +FUNC_NAME(lshift_func_int8_t_s_s)(int8_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((int)right) < 0) || (((int)right) >= 32) || (left > (INT8_MAX >> ((int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((int)right)); +} + +STATIC int8_t +FUNC_NAME(lshift_func_int8_t_s_u)(int8_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((unsigned int)right) >= 32) || (left > (INT8_MAX >> ((unsigned int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((unsigned int)right)); +} + +STATIC int8_t +FUNC_NAME(rshift_func_int8_t_s_s)(int8_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((int)right) < 0) || (((int)right) >= 32))? + (UNDEFINED(left)) : +#endif + (left >> ((int)right)); +} + +STATIC int8_t +FUNC_NAME(rshift_func_int8_t_s_u)(int8_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((unsigned int)right) >= 32)) ? + (UNDEFINED(left)) : +#endif + (left >> ((unsigned int)right)); +} + + + +STATIC int16_t +FUNC_NAME(unary_minus_func_int16_t_s)(int16_t si LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT16_MAX>=INT_MAX) + (si==INT16_MIN) ? + (UNDEFINED(si)) : +#endif +#endif + -si; +} + +STATIC int16_t +FUNC_NAME(add_func_int16_t_s_s)(int16_t si1, int16_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT16_MAX>=INT_MAX) + (((si1>0) && (si2>0) && (si1 > (INT16_MAX-si2))) || ((si1<0) && (si2<0) && (si1 < (INT16_MIN-si2)))) ? + (UNDEFINED(si1)) : +#endif +#endif + (si1 + si2); +} + +STATIC int16_t +FUNC_NAME(sub_func_int16_t_s_s)(int16_t si1, int16_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT16_MAX>=INT_MAX) + (((si1^si2) & (((si1 ^ ((si1^si2) & (~INT16_MAX)))-si2)^si2)) < 0) ? + (UNDEFINED(si1)) : +#endif +#endif + (si1 - si2); +} + +STATIC int16_t +FUNC_NAME(mul_func_int16_t_s_s)(int16_t si1, int16_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT16_MAX>=INT_MAX) + (((si1 > 0) && (si2 > 0) && (si1 > (INT16_MAX / si2))) || ((si1 > 0) && (si2 <= 0) && (si2 < (INT16_MIN / si1))) || ((si1 <= 0) && (si2 > 0) && (si1 < (INT16_MIN / si2))) || ((si1 <= 0) && (si2 <= 0) && (si1 != 0) && (si2 < (INT16_MAX / si1)))) ? + (UNDEFINED(si1)) : +#endif +#endif + si1 * si2; +} + +STATIC int16_t +FUNC_NAME(mod_func_int16_t_s_s)(int16_t si1, int16_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((si2 == 0) || ((si1 == INT16_MIN) && (si2 == (-1)))) ? + (UNDEFINED(si1)) : +#endif + (si1 % si2); +} + +STATIC int16_t +FUNC_NAME(div_func_int16_t_s_s)(int16_t si1, int16_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((si2 == 0) || ((si1 == INT16_MIN) && (si2 == (-1)))) ? + (UNDEFINED(si1)) : +#endif + (si1 / si2); +} + +STATIC int16_t +FUNC_NAME(lshift_func_int16_t_s_s)(int16_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((int)right) < 0) || (((int)right) >= 32) || (left > (INT16_MAX >> ((int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((int)right)); +} + +STATIC int16_t +FUNC_NAME(lshift_func_int16_t_s_u)(int16_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((unsigned int)right) >= 32) || (left > (INT16_MAX >> ((unsigned int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((unsigned int)right)); +} + +STATIC int16_t +FUNC_NAME(rshift_func_int16_t_s_s)(int16_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((int)right) < 0) || (((int)right) >= 32))? + (UNDEFINED(left)) : +#endif + (left >> ((int)right)); +} + +STATIC int16_t +FUNC_NAME(rshift_func_int16_t_s_u)(int16_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((unsigned int)right) >= 32)) ? + (UNDEFINED(left)) : +#endif + (left >> ((unsigned int)right)); +} + + + +STATIC int32_t +FUNC_NAME(unary_minus_func_int32_t_s)(int32_t si LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT32_MAX>=INT_MAX) + (si==INT32_MIN) ? + (UNDEFINED(si)) : +#endif +#endif + -si; +} + +STATIC int32_t +FUNC_NAME(add_func_int32_t_s_s)(int32_t si1, int32_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT32_MAX>=INT_MAX) + (((si1>0) && (si2>0) && (si1 > (INT32_MAX-si2))) || ((si1<0) && (si2<0) && (si1 < (INT32_MIN-si2)))) ? + (UNDEFINED(si1)) : +#endif +#endif + (si1 + si2); +} + +STATIC int32_t +FUNC_NAME(sub_func_int32_t_s_s)(int32_t si1, int32_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT32_MAX>=INT_MAX) + (((si1^si2) & (((si1 ^ ((si1^si2) & (~INT32_MAX)))-si2)^si2)) < 0) ? + (UNDEFINED(si1)) : +#endif +#endif + (si1 - si2); +} + +STATIC int32_t +FUNC_NAME(mul_func_int32_t_s_s)(int32_t si1, int32_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT32_MAX>=INT_MAX) + (((si1 > 0) && (si2 > 0) && (si1 > (INT32_MAX / si2))) || ((si1 > 0) && (si2 <= 0) && (si2 < (INT32_MIN / si1))) || ((si1 <= 0) && (si2 > 0) && (si1 < (INT32_MIN / si2))) || ((si1 <= 0) && (si2 <= 0) && (si1 != 0) && (si2 < (INT32_MAX / si1)))) ? + (UNDEFINED(si1)) : +#endif +#endif + si1 * si2; +} + +STATIC int32_t +FUNC_NAME(mod_func_int32_t_s_s)(int32_t si1, int32_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((si2 == 0) || ((si1 == INT32_MIN) && (si2 == (-1)))) ? + (UNDEFINED(si1)) : +#endif + (si1 % si2); +} + +STATIC int32_t +FUNC_NAME(div_func_int32_t_s_s)(int32_t si1, int32_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((si2 == 0) || ((si1 == INT32_MIN) && (si2 == (-1)))) ? + (UNDEFINED(si1)) : +#endif + (si1 / si2); +} + +STATIC int32_t +FUNC_NAME(lshift_func_int32_t_s_s)(int32_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((int)right) < 0) || (((int)right) >= 32) || (left > (INT32_MAX >> ((int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((int)right)); +} + +STATIC int32_t +FUNC_NAME(lshift_func_int32_t_s_u)(int32_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((unsigned int)right) >= 32) || (left > (INT32_MAX >> ((unsigned int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((unsigned int)right)); +} + +STATIC int32_t +FUNC_NAME(rshift_func_int32_t_s_s)(int32_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((int)right) < 0) || (((int)right) >= 32))? + (UNDEFINED(left)) : +#endif + (left >> ((int)right)); +} + +STATIC int32_t +FUNC_NAME(rshift_func_int32_t_s_u)(int32_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((unsigned int)right) >= 32)) ? + (UNDEFINED(left)) : +#endif + (left >> ((unsigned int)right)); +} + +#ifndef NO_LONGLONG + + +STATIC int64_t +FUNC_NAME(unary_minus_func_int64_t_s)(int64_t si LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT64_MAX>=INT_MAX) + (si==INT64_MIN) ? + (UNDEFINED(si)) : +#endif +#endif + -si; +} + +STATIC int64_t +FUNC_NAME(add_func_int64_t_s_s)(int64_t si1, int64_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT64_MAX>=INT_MAX) + (((si1>0) && (si2>0) && (si1 > (INT64_MAX-si2))) || ((si1<0) && (si2<0) && (si1 < (INT64_MIN-si2)))) ? + (UNDEFINED(si1)) : +#endif +#endif + (si1 + si2); +} + +STATIC int64_t +FUNC_NAME(sub_func_int64_t_s_s)(int64_t si1, int64_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT64_MAX>=INT_MAX) + (((si1^si2) & (((si1 ^ ((si1^si2) & (~INT64_MAX)))-si2)^si2)) < 0) ? + (UNDEFINED(si1)) : +#endif +#endif + (si1 - si2); +} + +STATIC int64_t +FUNC_NAME(mul_func_int64_t_s_s)(int64_t si1, int64_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE +#if (INT64_MAX>=INT_MAX) + (((si1 > 0) && (si2 > 0) && (si1 > (INT64_MAX / si2))) || ((si1 > 0) && (si2 <= 0) && (si2 < (INT64_MIN / si1))) || ((si1 <= 0) && (si2 > 0) && (si1 < (INT64_MIN / si2))) || ((si1 <= 0) && (si2 <= 0) && (si1 != 0) && (si2 < (INT64_MAX / si1)))) ? + (UNDEFINED(si1)) : +#endif +#endif + si1 * si2; +} + +STATIC int64_t +FUNC_NAME(mod_func_int64_t_s_s)(int64_t si1, int64_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((si2 == 0) || ((si1 == INT64_MIN) && (si2 == (-1)))) ? + (UNDEFINED(si1)) : +#endif + (si1 % si2); +} + +STATIC int64_t +FUNC_NAME(div_func_int64_t_s_s)(int64_t si1, int64_t si2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((si2 == 0) || ((si1 == INT64_MIN) && (si2 == (-1)))) ? + (UNDEFINED(si1)) : +#endif + (si1 / si2); +} + +STATIC int64_t +FUNC_NAME(lshift_func_int64_t_s_s)(int64_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((int)right) < 0) || (((int)right) >= 32) || (left > (INT64_MAX >> ((int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((int)right)); +} + +STATIC int64_t +FUNC_NAME(lshift_func_int64_t_s_u)(int64_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((unsigned int)right) >= 32) || (left > (INT64_MAX >> ((unsigned int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((unsigned int)right)); +} + +STATIC int64_t +FUNC_NAME(rshift_func_int64_t_s_s)(int64_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((int)right) < 0) || (((int)right) >= 32))? + (UNDEFINED(left)) : +#endif + (left >> ((int)right)); +} + +STATIC int64_t +FUNC_NAME(rshift_func_int64_t_s_u)(int64_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((left < 0) || (((unsigned int)right) >= 32)) ? + (UNDEFINED(left)) : +#endif + (left >> ((unsigned int)right)); +} + +#endif + + + + + +STATIC uint8_t +FUNC_NAME(unary_minus_func_uint8_t_u)(uint8_t ui LOG_INDEX) +{ + LOG_EXEC + return -ui; +} + +STATIC uint8_t +FUNC_NAME(add_func_uint8_t_u_u)(uint8_t ui1, uint8_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ui1 + ui2; +} + +STATIC uint8_t +FUNC_NAME(sub_func_uint8_t_u_u)(uint8_t ui1, uint8_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ui1 - ui2; +} + +STATIC uint8_t +FUNC_NAME(mul_func_uint8_t_u_u)(uint8_t ui1, uint8_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ((unsigned int)ui1) * ((unsigned int)ui2); +} + +STATIC uint8_t +FUNC_NAME(mod_func_uint8_t_u_u)(uint8_t ui1, uint8_t ui2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (ui2 == 0) ? + (UNDEFINED(ui1)) : +#endif + (ui1 % ui2); +} + +STATIC uint8_t +FUNC_NAME(div_func_uint8_t_u_u)(uint8_t ui1, uint8_t ui2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (ui2 == 0) ? + (UNDEFINED(ui1)) : +#endif + (ui1 / ui2); +} + +STATIC uint8_t +FUNC_NAME(lshift_func_uint8_t_u_s)(uint8_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((int)right) < 0) || (((int)right) >= 32) || (left > (UINT8_MAX >> ((int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((int)right)); +} + +STATIC uint8_t +FUNC_NAME(lshift_func_uint8_t_u_u)(uint8_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((unsigned int)right) >= 32) || (left > (UINT8_MAX >> ((unsigned int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((unsigned int)right)); +} + +STATIC uint8_t +FUNC_NAME(rshift_func_uint8_t_u_s)(uint8_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((int)right) < 0) || (((int)right) >= 32)) ? + (UNDEFINED(left)) : +#endif + (left >> ((int)right)); +} + +STATIC uint8_t +FUNC_NAME(rshift_func_uint8_t_u_u)(uint8_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (((unsigned int)right) >= 32) ? + (UNDEFINED(left)) : +#endif + (left >> ((unsigned int)right)); +} + + + +STATIC uint16_t +FUNC_NAME(unary_minus_func_uint16_t_u)(uint16_t ui LOG_INDEX) +{ + LOG_EXEC + return -ui; +} + +STATIC uint16_t +FUNC_NAME(add_func_uint16_t_u_u)(uint16_t ui1, uint16_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ui1 + ui2; +} + +STATIC uint16_t +FUNC_NAME(sub_func_uint16_t_u_u)(uint16_t ui1, uint16_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ui1 - ui2; +} + +STATIC uint16_t +FUNC_NAME(mul_func_uint16_t_u_u)(uint16_t ui1, uint16_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ((unsigned int)ui1) * ((unsigned int)ui2); +} + +STATIC uint16_t +FUNC_NAME(mod_func_uint16_t_u_u)(uint16_t ui1, uint16_t ui2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (ui2 == 0) ? + (UNDEFINED(ui1)) : +#endif + (ui1 % ui2); +} + +STATIC uint16_t +FUNC_NAME(div_func_uint16_t_u_u)(uint16_t ui1, uint16_t ui2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (ui2 == 0) ? + (UNDEFINED(ui1)) : +#endif + (ui1 / ui2); +} + +STATIC uint16_t +FUNC_NAME(lshift_func_uint16_t_u_s)(uint16_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((int)right) < 0) || (((int)right) >= 32) || (left > (UINT16_MAX >> ((int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((int)right)); +} + +STATIC uint16_t +FUNC_NAME(lshift_func_uint16_t_u_u)(uint16_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((unsigned int)right) >= 32) || (left > (UINT16_MAX >> ((unsigned int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((unsigned int)right)); +} + +STATIC uint16_t +FUNC_NAME(rshift_func_uint16_t_u_s)(uint16_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((int)right) < 0) || (((int)right) >= 32)) ? + (UNDEFINED(left)) : +#endif + (left >> ((int)right)); +} + +STATIC uint16_t +FUNC_NAME(rshift_func_uint16_t_u_u)(uint16_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (((unsigned int)right) >= 32) ? + (UNDEFINED(left)) : +#endif + (left >> ((unsigned int)right)); +} + + + +STATIC uint32_t +FUNC_NAME(unary_minus_func_uint32_t_u)(uint32_t ui LOG_INDEX) +{ + LOG_EXEC + return -ui; +} + +STATIC uint32_t +FUNC_NAME(add_func_uint32_t_u_u)(uint32_t ui1, uint32_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ui1 + ui2; +} + +STATIC uint32_t +FUNC_NAME(sub_func_uint32_t_u_u)(uint32_t ui1, uint32_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ui1 - ui2; +} + +STATIC uint32_t +FUNC_NAME(mul_func_uint32_t_u_u)(uint32_t ui1, uint32_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ((unsigned int)ui1) * ((unsigned int)ui2); +} + +STATIC uint32_t +FUNC_NAME(mod_func_uint32_t_u_u)(uint32_t ui1, uint32_t ui2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (ui2 == 0) ? + (UNDEFINED(ui1)) : +#endif + (ui1 % ui2); +} + +STATIC uint32_t +FUNC_NAME(div_func_uint32_t_u_u)(uint32_t ui1, uint32_t ui2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (ui2 == 0) ? + (UNDEFINED(ui1)) : +#endif + (ui1 / ui2); +} + +STATIC uint32_t +FUNC_NAME(lshift_func_uint32_t_u_s)(uint32_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((int)right) < 0) || (((int)right) >= 32) || (left > (UINT32_MAX >> ((int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((int)right)); +} + +STATIC uint32_t +FUNC_NAME(lshift_func_uint32_t_u_u)(uint32_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((unsigned int)right) >= 32) || (left > (UINT32_MAX >> ((unsigned int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((unsigned int)right)); +} + +STATIC uint32_t +FUNC_NAME(rshift_func_uint32_t_u_s)(uint32_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((int)right) < 0) || (((int)right) >= 32)) ? + (UNDEFINED(left)) : +#endif + (left >> ((int)right)); +} + +STATIC uint32_t +FUNC_NAME(rshift_func_uint32_t_u_u)(uint32_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (((unsigned int)right) >= 32) ? + (UNDEFINED(left)) : +#endif + (left >> ((unsigned int)right)); +} + +#ifndef NO_LONGLONG + + +STATIC uint64_t +FUNC_NAME(unary_minus_func_uint64_t_u)(uint64_t ui LOG_INDEX) +{ + LOG_EXEC + return -ui; +} + +STATIC uint64_t +FUNC_NAME(add_func_uint64_t_u_u)(uint64_t ui1, uint64_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ui1 + ui2; +} + +STATIC uint64_t +FUNC_NAME(sub_func_uint64_t_u_u)(uint64_t ui1, uint64_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ui1 - ui2; +} + +STATIC uint64_t +FUNC_NAME(mul_func_uint64_t_u_u)(uint64_t ui1, uint64_t ui2 LOG_INDEX) +{ + LOG_EXEC + return ((unsigned long long int)ui1) * ((unsigned long long int)ui2); +} + +STATIC uint64_t +FUNC_NAME(mod_func_uint64_t_u_u)(uint64_t ui1, uint64_t ui2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (ui2 == 0) ? + (UNDEFINED(ui1)) : +#endif + (ui1 % ui2); +} + +STATIC uint64_t +FUNC_NAME(div_func_uint64_t_u_u)(uint64_t ui1, uint64_t ui2 LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (ui2 == 0) ? + (UNDEFINED(ui1)) : +#endif + (ui1 / ui2); +} + +STATIC uint64_t +FUNC_NAME(lshift_func_uint64_t_u_s)(uint64_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((int)right) < 0) || (((int)right) >= 32) || (left > (UINT64_MAX >> ((int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((int)right)); +} + +STATIC uint64_t +FUNC_NAME(lshift_func_uint64_t_u_u)(uint64_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((unsigned int)right) >= 32) || (left > (UINT64_MAX >> ((unsigned int)right)))) ? + (UNDEFINED(left)) : +#endif + (left << ((unsigned int)right)); +} + +STATIC uint64_t +FUNC_NAME(rshift_func_uint64_t_u_s)(uint64_t left, int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + ((((int)right) < 0) || (((int)right) >= 32)) ? + (UNDEFINED(left)) : +#endif + (left >> ((int)right)); +} + +STATIC uint64_t +FUNC_NAME(rshift_func_uint64_t_u_u)(uint64_t left, unsigned int right LOG_INDEX) +{ + LOG_EXEC + return +#ifndef UNSAFE + (((unsigned int)right) >= 32) ? + (UNDEFINED(left)) : +#endif + (left >> ((unsigned int)right)); +} + +#endif + +#endif diff --git a/tests/gears.png b/tests/gears.png Binary files differindex ffb855c4..a35db625 100644 --- a/tests/gears.png +++ b/tests/gears.png diff --git a/tests/gl_ps.c b/tests/gl_ps.c index 81579c1d..6ea0e3db 100644 --- a/tests/gl_ps.c +++ b/tests/gl_ps.c @@ -78,6 +78,9 @@ void shaders() { glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &ok); assert(ok); + assert(glIsProgram(program)); + assert(!glIsProgram(0)); + assert(!glIsProgram(program+1)); // a number that can't be a real shader glUseProgram(program); diff --git a/tests/gl_ps.png b/tests/gl_ps.png Binary files differindex 185f7166..ac13ec0b 100644 --- a/tests/gl_ps.png +++ b/tests/gl_ps.png diff --git a/tests/gl_ps_packed.c b/tests/gl_ps_packed.c new file mode 100644 index 00000000..9ab99cb8 --- /dev/null +++ b/tests/gl_ps_packed.c @@ -0,0 +1,230 @@ +/******************************************************************* + * * + * 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_COORD_ARRAY); + 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_workaround.c b/tests/gl_ps_workaround.c new file mode 100644 index 00000000..1e2a5c41 --- /dev/null +++ b/tests/gl_ps_workaround.c @@ -0,0 +1,230 @@ +/******************************************************************* + * * + * 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 new file mode 100644 index 00000000..e5bd2fd1 --- /dev/null +++ b/tests/gl_ps_workaround2.c @@ -0,0 +1,230 @@ +/******************************************************************* + * * + * 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/glbook/CH13_ParticleSystem.png b/tests/glbook/CH13_ParticleSystem.png Binary files differindex ff9c3496..4b69414f 100644 --- a/tests/glbook/CH13_ParticleSystem.png +++ b/tests/glbook/CH13_ParticleSystem.png diff --git a/tests/perspective.c b/tests/perspective.c new file mode 100644 index 00000000..72f4c50f --- /dev/null +++ b/tests/perspective.c @@ -0,0 +1,408 @@ +/* + * SDL OpenGL Tutorial. + * (c) Michael Vance, 2000 + * briareos@lokigames.com + * + * Distributed under terms of the LGPL. + */ + +#include <SDL/SDL.h> + +#ifdef EMSCRIPTEN +#include <GL/gl.h> +#include <GL/glu.h> +#include "emscripten.h" +#else +#include <GL/gl.h> +#include <GL/glu.h> +#endif +#include <stdio.h> +#include <stdlib.h> + +#ifdef EMSCRIPTEN + #define emColor4ubv(x) +#else +#define emColor4ubv(x) glColor4ubv(x) +#endif + +static GLboolean should_rotate = GL_TRUE; + +static void quit_tutorial( int code ) +{ + /* + * Quit SDL so we can release the fullscreen + * mode and restore the previous video settings, + * etc. + */ + SDL_Quit( ); + + /* Exit program. */ + exit( code ); +} + +static void handle_key_down( SDL_keysym* keysym ) +{ + + /* + * We're only interested if 'Esc' has + * been presssed. + * + * EXERCISE: + * Handle the arrow keys and have that change the + * viewing position/angle. + */ + switch( keysym->sym ) { + case SDLK_ESCAPE: + quit_tutorial( 0 ); + break; + case SDLK_SPACE: + should_rotate = !should_rotate; + break; + default: + break; + } + +} + +static void process_events( void ) +{ + /* Our SDL event placeholder. */ + SDL_Event event; + + /* Grab all the events off the queue. */ + while( SDL_PollEvent( &event ) ) { + + switch( event.type ) { + case SDL_KEYDOWN: + /* Handle key presses. */ + handle_key_down( &event.key.keysym ); + break; + case SDL_QUIT: + /* Handle quit requests (like Ctrl-c). */ + quit_tutorial( 0 ); + break; + } + + } + +} + +static void draw_screen( void ) +{ + /* Our angle of rotation. */ + static float angle = 0.0f; + + /* + * EXERCISE: + * Replace this awful mess with vertex + * arrays and a call to glDrawElements. + * + * EXERCISE: + * After completing the above, change + * it to use compiled vertex arrays. + * + * EXERCISE: + * Verify my windings are correct here ;). + */ + static GLfloat v0[] = { -1.0f, -1.0f, 1.0f }; + static GLfloat v1[] = { 1.0f, -1.0f, 1.0f }; + static GLfloat v2[] = { 1.0f, 1.0f, 1.0f }; + static GLfloat v3[] = { -1.0f, 1.0f, 1.0f }; + static GLfloat v4[] = { -1.0f, -1.0f, -1.0f }; + static GLfloat v5[] = { 1.0f, -1.0f, -1.0f }; + static GLfloat v6[] = { 1.0f, 1.0f, -1.0f }; + static GLfloat v7[] = { -1.0f, 1.0f, -1.0f }; + static GLubyte red[] = { 255, 0, 0, 255 }; + static GLubyte green[] = { 0, 255, 0, 255 }; + static GLubyte blue[] = { 0, 0, 255, 255 }; + static GLubyte white[] = { 255, 255, 255, 255 }; + static GLubyte yellow[] = { 0, 255, 255, 255 }; + static GLubyte black[] = { 0, 0, 0, 255 }; + static GLubyte orange[] = { 255, 255, 0, 255 }; + static GLubyte purple[] = { 255, 0, 255, 0 }; + + /* Clear the color and depth buffers. */ + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + /* We don't want to modify the projection matrix. */ + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity( ); + + /* Move down the z-axis. */ + glTranslatef( 0.0, 0.0, -5.0 ); + + /* Rotate. */ + glRotatef( angle, 0.0, 1.0, 0.0 ); + + if( should_rotate ) { + + if( ++angle > 360.0f ) { + angle = 0.0f; + } + + } + + /* Send our triangle data to the pipeline. */ + glBegin( GL_TRIANGLES ); + + emColor4ubv( red ); + glVertex3fv( v0 ); + emColor4ubv( green ); + glVertex3fv( v1 ); + emColor4ubv( blue ); + glVertex3fv( v2 ); + + emColor4ubv( red ); + glVertex3fv( v0 ); + emColor4ubv( blue ); + glVertex3fv( v2 ); + emColor4ubv( white ); + glVertex3fv( v3 ); + + emColor4ubv( green ); + glVertex3fv( v1 ); + emColor4ubv( black ); + glVertex3fv( v5 ); + emColor4ubv( orange ); + glVertex3fv( v6 ); + + emColor4ubv( green ); + glVertex3fv( v1 ); + emColor4ubv( orange ); + glVertex3fv( v6 ); + emColor4ubv( blue ); + glVertex3fv( v2 ); + + emColor4ubv( black ); + glVertex3fv( v5 ); + emColor4ubv( yellow ); + glVertex3fv( v4 ); + emColor4ubv( purple ); + glVertex3fv( v7 ); + + emColor4ubv( black ); + glVertex3fv( v5 ); + emColor4ubv( purple ); + glVertex3fv( v7 ); + emColor4ubv( orange ); + glVertex3fv( v6 ); + + emColor4ubv( yellow ); + glVertex3fv( v4 ); + emColor4ubv( red ); + glVertex3fv( v0 ); + emColor4ubv( white ); + glVertex3fv( v3 ); + + emColor4ubv( yellow ); + glVertex3fv( v4 ); + emColor4ubv( white ); + glVertex3fv( v3 ); + emColor4ubv( purple ); + glVertex3fv( v7 ); + + emColor4ubv( white ); + glVertex3fv( v3 ); + emColor4ubv( blue ); + glVertex3fv( v2 ); + emColor4ubv( orange ); + glVertex3fv( v6 ); + + emColor4ubv( white ); + glVertex3fv( v3 ); + emColor4ubv( orange ); + glVertex3fv( v6 ); + emColor4ubv( purple ); + glVertex3fv( v7 ); + + emColor4ubv( green ); + glVertex3fv( v1 ); + emColor4ubv( red ); + glVertex3fv( v0 ); + emColor4ubv( yellow ); + glVertex3fv( v4 ); + + emColor4ubv( green ); + glVertex3fv( v1 ); + emColor4ubv( yellow ); + glVertex3fv( v4 ); + emColor4ubv( black ); + glVertex3fv( v5 ); + + glEnd( ); + + /* + * EXERCISE: + * Draw text telling the user that 'Spc' + * pauses the rotation and 'Esc' quits. + * Do it using vetors and textured quads. + */ + + /* + * Swap the buffers. This this tells the driver to + * render the next frame from the contents of the + * back-buffer, and to set all rendering operations + * to occur on what was the front-buffer. + * + * Double buffering prevents nasty visual tearing + * from the application drawing on areas of the + * screen that are being updated at the same time. + */ + SDL_GL_SwapBuffers( ); +} + +static void setup_opengl( int width, int height ) +{ + float ratio = (float) width / (float) height; + + /* Our shading model--Gouraud (smooth). */ + glShadeModel( GL_SMOOTH ); + + /* Culling. */ + glCullFace( GL_BACK ); + glFrontFace( GL_CCW ); + glEnable( GL_CULL_FACE ); + + /* Set the clear color. */ + glClearColor( 0, 0, 0, 0 ); + + /* Setup our viewport. */ + glViewport( 0, 0, width, height ); + + /* + * Change to the projection matrix and set + * our viewing volume. + */ + glMatrixMode( GL_PROJECTION ); + glLoadIdentity( ); + /* + * EXERCISE: + * Replace this with a call to glFrustum. + */ + gluPerspective( 60.0, ratio, 1.0, 1024.0 ); +} + +void one_iter(); +void one_iter() { + process_events( ); + /* Draw the screen. */ + draw_screen( ); +} + +int main( int argc, char* argv[] ) +{ + /* Information about the current video settings. */ + const SDL_VideoInfo* info = NULL; + /* Dimensions of our window. */ + int width = 0; + int height = 0; + /* Color depth in bits of our window. */ + int bpp = 0; + /* Flags we will pass into SDL_SetVideoMode. */ + int flags = 0; + + /* First, initialize SDL's video subsystem. */ + if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { + /* Failed, exit. */ + fprintf( stderr, "Video initialization failed: %s\n", + SDL_GetError( ) ); + quit_tutorial( 1 ); + } + + /* Let's get some video information. */ + info = SDL_GetVideoInfo( ); + + if( !info ) { + /* This should probably never happen. */ + fprintf( stderr, "Video query failed: %s\n", + SDL_GetError( ) ); + quit_tutorial( 1 ); + } + + /* + * Set our width/height to 640/480 (you would + * of course let the user decide this in a normal + * app). We get the bpp we will request from + * the display. On X11, VidMode can't change + * resolution, so this is probably being overly + * safe. Under Win32, ChangeDisplaySettings + * can change the bpp. + */ + width = 640; + height = 480; + bpp = info->vfmt->BitsPerPixel; + + /* + * Now, we want to setup our requested + * window attributes for our OpenGL window. + * We want *at least* 5 bits of red, green + * and blue. We also want at least a 16-bit + * depth buffer. + * + * The last thing we do is request a double + * buffered window. '1' turns on double + * buffering, '0' turns it off. + * + * Note that we do not use SDL_DOUBLEBUF in + * the flags to SDL_SetVideoMode. That does + * not affect the GL attribute state, only + * the standard 2D blitting setup. + */ +// SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); +// SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); +// SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); +// SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); +// SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + + /* + * We want to request that SDL provide us + * with an OpenGL window, in a fullscreen + * video mode. + * + * EXERCISE: + * Make starting windowed an option, and + * handle the resize events properly with + * glViewport. + */ + flags = SDL_OPENGL;// | SDL_FULLSCREEN; + + /* + * Set the video mode + */ + if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) { + /* + * This could happen for a variety of reasons, + * including DISPLAY not being set, the specified + * resolution not being available, etc. + */ + fprintf( stderr, "Video mode set failed: %s\n", + SDL_GetError( ) ); + quit_tutorial( 1 ); + } + + /* + * At this point, we should have a properly setup + * double-buffered window for use with OpenGL. + */ + setup_opengl( width, height ); + + /* + * Now we want to begin our normal app process-- + * an event loop with a lot of redrawing. + */ + one_iter(); // just one for testing purposes + +#ifndef EMSCRIPTEN + SDL_Delay(2000); +#endif + + /* + * EXERCISE: + * Record timings using SDL_GetTicks() and + * and print out frames per second at program + * end. + */ + + /* Never reached. */ + return 0; +} diff --git a/tests/perspective.png b/tests/perspective.png Binary files differnew file mode 100644 index 00000000..04cedc71 --- /dev/null +++ b/tests/perspective.png diff --git a/tests/runner.py b/tests/runner.py index b6980933..96a2dabd 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -100,14 +100,8 @@ class RunnerCore(unittest.TestCase): for temp_file in os.listdir(TEMP_DIR): if temp_file.endswith('.ll'): self.has_prev_ll = True - + def tearDown(self): - if self.save_JS: - for name in os.listdir(self.get_dir()): - if name.endswith(('.o.js', '.cc.js')): - suff = '.'.join(name.split('.')[-2:]) - shutil.copy(os.path.join(self.get_dir(), name), - os.path.join(TEMP_DIR, self.id().replace('__main__.', '').replace('.test_', '.')+'.'+suff)) if not self.save_dir: # rmtree() fails on Windows if the current working directory is inside the tree. os.chdir(os.path.join(self.get_dir(), '..')) @@ -140,6 +134,12 @@ class RunnerCore(unittest.TestCase): def get_stdout_path(self): return os.path.join(self.get_dir(), 'stdout') + def hardcode_arguments(self, filename, args): + # Hardcode in the arguments, so js is portable without manual commandlinearguments + if not args: return + js = open(filename).read() + open(filename, 'w').write(js.replace('var ret = run();', 'var ret = run(%s);' % str(args))) + def prep_ll_run(self, filename, ll_file, force_recompile=False, build_ll_hook=None): if ll_file.endswith(('.bc', '.o')): if ll_file != filename + '.o': @@ -435,6 +435,8 @@ process(sys.argv[1]) sys.argv = map(lambda arg: arg if not arg.startswith('test_') else 'default.' + arg, sys.argv) +test_index = 0 + if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'browser' not in str(sys.argv): # Tests @@ -448,29 +450,35 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows class T(RunnerCore): # Short name, to make it more fun to use manually on the commandline ## Does a complete test - builds, runs, checks output, etc. def do_run(self, src, expected_output, args=[], output_nicerizer=None, output_processor=None, no_build=False, main_file=None, additional_files=[], js_engines=None, post_build=None, basename='src.cpp', libraries=[], includes=[], force_c=False, build_ll_hook=None, extra_emscripten_args=[]): - if force_c or (main_file is not None and main_file[-2:]) == '.c': - basename = 'src.c' - Building.COMPILER = to_cc(Building.COMPILER) - - dirname = self.get_dir() - filename = os.path.join(dirname, basename) - if not no_build: - self.build(src, dirname, filename, main_file=main_file, additional_files=additional_files, libraries=libraries, includes=includes, - build_ll_hook=build_ll_hook, extra_emscripten_args=extra_emscripten_args, post_build=post_build) - - # Run in both JavaScript engines, if optimizing - significant differences there (typed arrays) - if js_engines is None: - js_engines = JS_ENGINES - if Settings.USE_TYPED_ARRAYS: - js_engines = filter(lambda engine: engine != V8_ENGINE, js_engines) # V8 issue 1822 - js_engines = filter(lambda engine: engine not in self.banned_js_engines, js_engines) - if len(js_engines) == 0: return self.skip('No JS engine present to run this test with. Check %s and the paths therein.' % EM_CONFIG) - for engine in js_engines: - js_output = self.run_generated_code(engine, filename + '.o.js', args, output_nicerizer=output_nicerizer) - self.assertContained(expected_output, js_output.replace('\r\n', '\n')) - self.assertNotContained('ERROR', js_output) - - #shutil.rmtree(dirname) # TODO: leave no trace in memory. But for now nice for debugging + if force_c or (main_file is not None and main_file[-2:]) == '.c': + basename = 'src.c' + Building.COMPILER = to_cc(Building.COMPILER) + + dirname = self.get_dir() + filename = os.path.join(dirname, basename) + if not no_build: + self.build(src, dirname, filename, main_file=main_file, additional_files=additional_files, libraries=libraries, includes=includes, + build_ll_hook=build_ll_hook, extra_emscripten_args=extra_emscripten_args, post_build=post_build) + + # Run in both JavaScript engines, if optimizing - significant differences there (typed arrays) + if js_engines is None: + js_engines = JS_ENGINES + if Settings.USE_TYPED_ARRAYS: + js_engines = filter(lambda engine: engine != V8_ENGINE, js_engines) # V8 issue 1822 + js_engines = filter(lambda engine: engine not in self.banned_js_engines, js_engines) + if len(js_engines) == 0: return self.skip('No JS engine present to run this test with. Check %s and the paths therein.' % EM_CONFIG) + for engine in js_engines: + js_output = self.run_generated_code(engine, filename + '.o.js', args, output_nicerizer=output_nicerizer) + self.assertContained(expected_output, js_output.replace('\r\n', '\n')) + self.assertNotContained('ERROR', js_output) + + #shutil.rmtree(dirname) # TODO: leave no trace in memory. But for now nice for debugging + + if self.save_JS: + global test_index + self.hardcode_arguments(filename + '.o.js', args) + shutil.copyfile(filename + '.o.js', os.path.join(TEMP_DIR, str(test_index) + '.js')) + test_index += 1 # No building - just process an existing .ll file (or .bc, which we turn into .ll) def do_ll_run(self, ll_file, expected_output=None, args=[], js_engines=None, output_nicerizer=None, post_build=None, force_recompile=False, build_ll_hook=None, extra_emscripten_args=[]): @@ -1131,7 +1139,6 @@ m_divisor is 1091269979 def test_i32_mul_precise(self): if self.emcc_args == None: return self.skip('needs ta2') - self.emcc_args += ['-s', 'PRECISE_I32_MUL=1'] src = r''' #include <stdio.h> @@ -1146,6 +1153,10 @@ m_divisor is 1091269979 self.do_run(src, '3217489085') def test_i32_mul_semiprecise(self): + if Settings.ASM_JS: return self.skip('asm is always fully precise') + + Settings.PRECISE_I32_MUL = 0 # we want semiprecise here + src = r''' #include <stdio.h> @@ -2845,6 +2856,23 @@ Exiting setjmp function, level: 0, prev_jmp: -1 ''' self.do_run(src, 'a1: 0\na2: 0\na3: 1\nb1: 0\nb2: 1\nb3: 1\nc1: 1\nc2: 1\nc3: 1\n') + def test_dynamic_cast_2(self): + if self.emcc_args is None: return self.skip('need libcxxabi') + + src = r''' + #include <stdio.h> + #include <typeinfo> + + class Class {}; + + int main() { + const Class* dp = dynamic_cast<const Class*>(&typeid(Class)); + // should return dp == NULL, + printf("pointer: %p\n", dp); + } + ''' + self.do_run(src, "pointer: (nil)") + def test_funcptr(self): src = ''' #include <stdio.h> @@ -3966,6 +3994,18 @@ The current type of b is: 9 ''' self.do_run(src, '*0\n') + def test_time_c(self): + src = r''' + #include <time.h> + #include <stdio.h> + + int main() { + time_t t = time(0); + printf("time: %s\n", ctime(&t)); + } + ''' + self.do_run(src, 'time: ') # compilation check, mainly + def test_intentional_fault(self): if Settings.ASM_JS: return self.skip('no throw support in asm') # Some programs intentionally segfault themselves, we should compile that into a throw @@ -4095,10 +4135,12 @@ The current type of b is: 9 ''' self.do_run(src, '*0.00,0.00,0.00*\n*0,77,0*\n*0,77,0*\n*0,77,0*') - def test_memcpy(self): + def test_memcpy_memcmp(self): src = ''' #include <stdio.h> #include <string.h> + #include <assert.h> + #define MAXX 48 void reset(unsigned char *buffer) { for (int i = 0; i < MAXX; i++) buffer[i] = i+1; @@ -4119,6 +4161,20 @@ The current type of b is: 9 reset(buffer); memcpy(buffer+i, buffer+j, k); dump(buffer); + assert(memcmp(buffer+i, buffer+j, k) == 0); + buffer[i + k/2]++; + if (buffer[i + k/2] != 0) { + assert(memcmp(buffer+i, buffer+j, k) > 0); + } else { + assert(memcmp(buffer+i, buffer+j, k) < 0); + } + buffer[i + k/2]--; + buffer[j + k/2]++; + if (buffer[j + k/2] != 0) { + assert(memcmp(buffer+i, buffer+j, k) < 0); + } else { + assert(memcmp(buffer+i, buffer+j, k) > 0); + } } } } @@ -4197,6 +4253,19 @@ The current type of b is: 9 ''' self.do_run(src, 'final: -403200.'); + def test_memmove3(self): + src = ''' + #include <stdio.h> + #include <string.h> + int main() { + char str[] = "memmove can be vvery useful....!"; + memmove(str+15, str+16, 17); + puts(str); + return 0; + } + ''' + self.do_run(src, 'memmove can be very useful....!') + def test_bsearch(self): if Settings.QUANTUM_SIZE == 1: return self.skip('Test cannot work with q1') @@ -5299,9 +5368,30 @@ Pass: 0.000012 0.000012''') return(0); } ''' - self.do_run(src, '3\nday 19, month Nov, year 2012'); + def test_sscanf_5(self): + src = r''' + #include "stdio.h" + + static const char *colors[] = { + " c black", + ". c #001100", + "X c #111100" + }; + + int main(){ + unsigned char code; + char color[32]; + int rcode; + for(int i = 0; i < 3; i++) { + rcode = sscanf(colors[i], "%c c %s", &code, color); + printf("%i, %c, %s\n", rcode, code, color); + } + } + ''' + self.do_run(src, '2, , black\n2, ., #001100\n2, X, #111100'); + def test_langinfo(self): src = open(path_from_root('tests', 'langinfo', 'test.c'), 'r').read() expected = open(path_from_root('tests', 'langinfo', 'output.txt'), 'r').read() @@ -6283,6 +6373,53 @@ int main(int argc, char **argv) { self.do_run(src, '789:123.46\n0:100.1') + def test_reinterpreted_ptrs(self): + if self.emcc_args is None: return self.skip('needs emcc and libc') + + src = r''' +#include <stdio.h> + +class Foo { +private: + float bar; +public: + int baz; + + Foo(): bar(0), baz(4711) {}; + + int getBar() const; +}; + +int Foo::getBar() const { + return this->bar; +}; + +const Foo *magic1 = reinterpret_cast<Foo*>(0xDEAD111F); +const Foo *magic2 = reinterpret_cast<Foo*>(0xDEAD888F); + +static void runTest() { + + const Foo *a = new Foo(); + const Foo *b = a; + + if (a->getBar() == 0) { + if (a->baz == 4712) + b = magic1; + else + b = magic2; + } + + printf("%s\n", (b == magic1 ? "magic1" : (b == magic2 ? "magic2" : "neither"))); +}; + +extern "C" { + int main(int argc, char **argv) { + runTest(); + } +} +''' + self.do_run(src, 'magic2') + def test_jansson(self): return self.skip('currently broken') @@ -6783,7 +6920,7 @@ def process(filename): if self.emcc_args is None: return self.skip('Very slow without ta2, and we would also need to include dlmalloc manually without emcc') if Settings.QUANTUM_SIZE == 1: return self.skip('TODO FIXME') - Settings.CORRECT_SIGNS = 1 # XXX: in default, we fail with 2 here, even though the pgo_data should be correct (and works in s_0_0). Investigate this. + Settings.CORRECT_SIGNS = 1 Settings.CORRECT_OVERFLOWS = 0 Settings.CORRECT_ROUNDINGS = 0 if self.emcc_args is None: Settings.SAFE_HEAP = 0 # uses time.h to set random bytes, other stuff @@ -6995,6 +7132,14 @@ def process(filename): self.assertIdentical(clean(open('release.js').read()), clean(open('debug%d.js' % debug).read())) # EMCC_DEBUG=1 mode must not generate different code! print >> sys.stderr, 'debug check %d passed too' % debug + try: + os.environ['EMCC_FORCE_STDLIBS'] = '1' + print 'EMCC_FORCE_STDLIBS' + do_test() + finally: + del os.environ['EMCC_FORCE_STDLIBS'] + print >> sys.stderr, 'EMCC_FORCE_STDLIBS ok' + try_delete(CANONICAL_TEMP_DIR) else: print >> sys.stderr, 'not doing debug check' @@ -7062,6 +7207,16 @@ def process(filename): finally: del os.environ['EMCC_LEAVE_INPUTS_RAW'] + def test_fuzz(self): + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2') + + Building.COMPILER_TEST_OPTS += ['-I' + path_from_root('tests', 'fuzz')] + + for name in glob.glob(path_from_root('tests', 'fuzz', '*.c')): + print name + self.do_run(open(path_from_root('tests', 'fuzz', name)).read(), + open(path_from_root('tests', 'fuzz', name + '.txt')).read(), force_c=True) + # Autodebug the code def do_autodebug(self, filename): output = Popen([PYTHON, AUTODEBUGGER, filename+'.o.ll', filename+'.o.ll.ll'], stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] @@ -7113,40 +7268,101 @@ def process(filename): ''' self.do_run(src, '''AD:-1,1''', build_ll_hook=self.do_autodebug) - def test_profiling(self): - if Settings.ASM_JS: return self.skip('asm does not support profiling') + def test_corruption(self): + if Settings.ASM_JS: return self.skip('cannot use corruption checks in asm') + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2 for actual test') - src = ''' - #include <emscripten.h> - #include <unistd.h> + Settings.CORRUPTION_CHECK = 1 - int main() + src = r''' + #include <stdio.h> + #include <stdlib.h> + #include <string.h> + int main(int argc, char **argv) { + int size = 1024*argc; + char *buffer = (char*)malloc(size); + #if CORRUPT + memset(buffer, argc, size+15); + #else + memset(buffer, argc, size); + #endif + for (int x = 0; x < size; x += argc*3) buffer[x] = x/3; + int ret = 0; + for (int x = 0; x < size; x++) ret += buffer[x]; + free(buffer); + printf("All ok, %d\n", ret); + } + ''' + + for corrupt in [1]: + self.do_run(src.replace('CORRUPT', str(corrupt)), 'Heap corruption detected!' if corrupt else 'All ok, 4209') + + def test_corruption_2(self): + if Settings.ASM_JS: return self.skip('cannot use corruption checks in asm') + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2 for actual test') + + Settings.SAFE_HEAP = 1 + Settings.CORRUPTION_CHECK = 1 + + # test for free(0), malloc(0), etc. + src = r''' + #include <iostream> + #include <fstream> + #include <stdlib.h> + #include <stdio.h> + + void bye() { + printf("all ok\n"); + } + + int main() { + atexit(bye); + + std::string testPath = "/Script/WA-KA.txt"; + std::fstream str(testPath.c_str(), std::ios::in | std::ios::binary); + + if (str.is_open()) { - EMSCRIPTEN_PROFILE_INIT(3); - EMSCRIPTEN_PROFILE_BEGIN(0); - usleep(10 * 1000); - EMSCRIPTEN_PROFILE_END(0); - EMSCRIPTEN_PROFILE_BEGIN(1); - usleep(50 * 1000); - EMSCRIPTEN_PROFILE_END(1); - EMSCRIPTEN_PROFILE_BEGIN(2); - usleep(250 * 1000); - EMSCRIPTEN_PROFILE_END(2); - return 0; + std::cout << "open!" << std::endl; + } else { + std::cout << "missing!" << std::endl; } + + return 1; + } ''' + self.do_run(src, 'missing!\nall ok\n') - post1 = ''' -def process(filename): - src = open(filename, 'a') - src.write(\'\'\' - Profiling.dump(); - \'\'\') - src.close() -''' + def test_corruption_3(self): + if Settings.ASM_JS: return self.skip('cannot use corruption checks in asm') + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('needs ta2 for actual test') - self.do_run(src, '''Profiling data: -Block 0: ''', post_build=post1) + Settings.CORRUPTION_CHECK = 1 + + # realloc + src = r''' + #include <stdlib.h> + #include <stdio.h> + #include <assert.h> + + void bye() { + printf("all ok\n"); + } + + int main(int argc, char **argv) { + atexit(bye); + + char *buffer = (char*)malloc(100); + for (int i = 0; i < 100; i++) buffer[i] = (i*i)%256; + buffer = (char*)realloc(buffer, argc + 50); + for (int i = 0; i < argc + 50; i++) { + //printf("%d : %d : %d : %d\n", i, (int)(buffer + i), buffer[i], (char)((i*i)%256)); + assert(buffer[i] == (char)((i*i)%256)); + } + return 1; + } + ''' + self.do_run(src, 'all ok\n') ### Integration tests @@ -7676,6 +7892,8 @@ def process(filename): def test_debug(self): if '-g' not in Building.COMPILER_TEST_OPTS: Building.COMPILER_TEST_OPTS.append('-g') + if self.emcc_args is not None: + if '-O1' in self.emcc_args or '-O2' in self.emcc_args: return self.skip('optimizations remove LLVM debug info') src = ''' #include <stdio.h> @@ -8051,7 +8269,6 @@ class %s(T): Settings.ASSERTIONS = 1-embetter Settings.SAFE_HEAP = 1-(embetter and llvm_opts) Building.LLVM_OPTS = llvm_opts - Settings.PGO = 0 Settings.CHECK_OVERFLOWS = 1-(embetter or llvm_opts) Settings.CORRECT_OVERFLOWS = 1-(embetter and llvm_opts) Settings.CORRECT_SIGNS = 0 @@ -8061,7 +8278,6 @@ class %s(T): Settings.INIT_STACK = 0 Settings.RUNTIME_TYPE_INFO = 0 Settings.DISABLE_EXCEPTION_CATCHING = 0 - Settings.PROFILE = 0 Settings.INCLUDE_FULL_LIBRARY = 0 Settings.BUILD_AS_SHARED_LIB = 0 Settings.RUNTIME_LINKED_LIBS = [] @@ -8084,11 +8300,11 @@ TT = %s exec('o1 = make_run("o1", compiler=CLANG, emcc_args=["-O1", "-s", "SAFE_HEAP=1"])') # Make one run with -O2, but without closure (we enable closure in specific tests, otherwise on everything it is too slow) - exec('o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2", "--closure", "0"])') + exec('o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2"])') # asm.js - #exec('asm = make_run("asm", compiler=CLANG, emcc_args=["-O0", "--closure", "0", "-s", "ASM_JS=1"])') - exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2", "--closure", "0", "-s", "ASM_JS=1"])') + #exec('asm = make_run("asm", compiler=CLANG, emcc_args=["-O0", "-s", "ASM_JS=1"])') + exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=1"])') # Make custom runs with various options for compiler, quantum, embetter, typed_arrays, llvm_opts in [ @@ -8114,11 +8330,12 @@ TT = %s # --version output = Popen([PYTHON, compiler, '--version'], stdout=PIPE, stderr=PIPE).communicate() - self.assertContained('''emcc (Emscripten GCC-like replacement) 2.0 -Copyright (C) 2012 the Emscripten authors. + output = output[0].replace('\r', '') + self.assertContained('''emcc (Emscripten GCC-like replacement)''', output) + self.assertContained('''Copyright (C) 2013 the Emscripten authors (see AUTHORS.txt) This is free and open source software under the MIT license. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -''', output[0].replace('\r', ''), output[1].replace('\r', '')) +''', output) # -v, without input files output = Popen([PYTHON, compiler, '-v'], stdout=PIPE, stderr=PIPE).communicate() @@ -8224,20 +8441,22 @@ Options that are modified or new in %s include: (['-o', 'something.js', '-O0'], 0, None, 0, 0), (['-o', 'something.js', '-O1'], 1, None, 0, 0), (['-o', 'something.js', '-O1', '--closure', '1'], 1, None, 1, 0), - (['-o', 'something.js', '-O2'], 2, None, 1, 1), + (['-o', 'something.js', '-O2'], 2, None, 0, 1), (['-o', 'something.js', '-O2', '--closure', '0'], 2, None, 0, 0), + (['-o', 'something.js', '-O2', '-g'], 2, None, 0, 0), (['-o', 'something.js', '-O3'], 3, None, 1, 1), (['-o', 'something.js', '-O3', '--closure', '0'], 3, None, 0, 0), # and, test compiling to bitcode first (['-o', 'something.bc'], 0, [], 0, 0), (['-o', 'something.bc'], 0, ['-O0'], 0, 0), (['-o', 'something.bc'], 1, ['-O1'], 0, 0), - (['-o', 'something.bc'], 2, ['-O2'], 1, 0), + (['-o', 'something.bc'], 2, ['-O2'], 0, 0), (['-o', 'something.bc'], 3, ['-O3'], 1, 0), (['-O1', '-o', 'something.bc'], 0, [], 0, 0), # -Ox is ignored and warned about ]: - #print params, opt_level, bc_params, closure + print params, opt_level, bc_params, closure, has_malloc self.clear() + keep_debug = '-g' in params output = Popen([PYTHON, compiler, path_from_root('tests', 'hello_world_loop' + ('_malloc' if has_malloc else '') + '.cpp')] + params, stdout=PIPE, stderr=PIPE).communicate() assert len(output[0]) == 0, output[0] @@ -8261,14 +8480,13 @@ Options that are modified or new in %s include: else: # closure has not been run, we can do some additional checks. TODO: figure out how to do these even with closure assert 'Module._main = ' not in generated, 'closure compiler should not have been run' - # XXX find a way to test this: assert ('& 255' in generated or '&255' in generated) == (opt_level <= 2), 'corrections should be in opt <= 2' - assert ('(label)' in generated) == (opt_level <= 1), 'relooping should be in opt >= 2' - assert ('assert(STACKTOP < STACK_MAX' in generated) == (opt_level == 0), 'assertions should be in opt == 0' - assert 'var $i;' in generated or 'var $i_0' in generated or 'var $storemerge3;' in generated or 'var $storemerge4;' in generated or 'var $i_04;' in generated, 'micro opts should always be on' + if keep_debug: + assert ('(label)' in generated) == (opt_level <= 1), 'relooping should be in opt >= 2' + assert ('assert(STACKTOP < STACK_MAX' in generated) == (opt_level == 0), 'assertions should be in opt == 0' + assert 'var $i;' in generated or 'var $i_0' in generated or 'var $storemerge3;' in generated or 'var $storemerge4;' in generated or 'var $i_04;' in generated, 'micro opts should always be on' if opt_level >= 2: - assert re.search('HEAP8\[\$\w+ \+ \(+\$\w+ ', generated) or re.search('HEAP8\[HEAP32\[', generated), 'eliminator should create compound expressions, and fewer one-time vars' # also in -O1, but easier to test in -O2 + assert re.search('HEAP8\[\$?\w+ \+ \(+\$?\w+ ', generated) or re.search('HEAP8\[HEAP32\[', generated), 'eliminator should create compound expressions, and fewer one-time vars' # also in -O1, but easier to test in -O2 assert ('_puts(' in generated) == (opt_level >= 1), 'with opt >= 1, llvm opts are run and they should optimize printf to puts' - assert ('function _malloc(bytes) {' in generated) == (not has_malloc), 'If malloc is needed, it should be there, if not not' assert 'function _main() {' in generated, 'Should be unminified, including whitespace' assert ('-O3' in (params+(bc_params or []))) or'function _dump' in generated, 'No inlining by default' @@ -8588,6 +8806,21 @@ f.close() self.assertContained('result: 62', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + def test_asm_undefined(self): + src = r''' + #include <stdio.h> + extern void doit(); + int main(int argc, char **argv) { + if (argc == 121) doit(); + printf("done\n"); + return 1; + } + ''' + filename = self.in_dir('src.cpp') + open(filename, 'w').write(src) + out, err = Popen([PYTHON, EMCC, filename, '-s', 'ASM_JS=1', '-O2'], stderr=PIPE).communicate() + assert 'Warning: Unresolved symbol' in err, 'always warn on undefs in asm, since it breaks validation' + def test_redundant_link(self): lib = "int mult() { return 1; }" lib_name = os.path.join(self.get_dir(), 'libA.c') @@ -9011,7 +9244,7 @@ f.close() return 0; } ''') - Popen([PYTHON, EMCC, '-O2', '--closure', '-0', os.path.join(self.get_dir(), 'main.cpp')]).communicate() + Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'main.cpp')]).communicate() output = run_js(os.path.join(self.get_dir(), 'a.out.js'), full_output=True, stderr=PIPE) self.assertContained('''0:0 1:1 @@ -9223,6 +9456,26 @@ f.close() finally: del os.environ['EMCC_DEBUG'] + def test_debuginfo(self): + if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode') + try: + os.environ['EMCC_DEBUG'] = '1' + # llvm debug info is kept only when we can see it, which is without the js optimize, -O0. js debug info is lost by registerize in -O2, so - g disables it + for args, expect_llvm, expect_js in [ + (['-O0'], True, True), + (['-O0', '-g'], True, True), + (['-O1'], False, True), + (['-O1', '-g'], False, True), + (['-O2'], False, False), + (['-O2', '-g'], False, True), + ]: + print args, expect_llvm, expect_js + output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp')] + args, stdout=PIPE, stderr=PIPE).communicate() + assert expect_llvm == ('strip-debug' not in err) + assert expect_js == ('registerize' not in err) + finally: + del os.environ['EMCC_DEBUG'] + def test_scons(self): # also incidentally tests c++11 integration in llvm 3.1 try_delete(os.path.join(self.get_dir(), 'test')) shutil.copytree(path_from_root('tests', 'scons'), os.path.join(self.get_dir(), 'test')) @@ -9958,6 +10211,12 @@ elif 'browser' in str(sys.argv): Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_image.c'), '-O2', '--preload-file', 'screenshot.jpg', '-o', 'page.html']).communicate() self.run_browser('page.html', '', '/report_result?600') + def test_sdl_image_jpeg(self): + shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.jpeg')) + open(os.path.join(self.get_dir(), 'sdl_image_jpeg.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_image_jpeg.c')).read())) + Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'sdl_image_jpeg.c'), '--preload-file', 'screenshot.jpeg', '-o', 'page.html']).communicate() + self.run_browser('page.html', '', '/report_result?600') + def test_sdl_image_compressed(self): for image, width in [(path_from_root('tests', 'screenshot2.png'), 300), (path_from_root('tests', 'screenshot.jpg'), 600)]: @@ -9977,12 +10236,12 @@ elif 'browser' in str(sys.argv): self.run_browser('page.html', '', '/report_result?' + str(width)) def test_sdl_image_prepare(self): - # load an image file, get pixel data. Also O2 coverage for --preload-file + # load an image file, get pixel data. shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.not')) self.btest('sdl_image_prepare.c', reference='screenshot.jpg', args=['--preload-file', 'screenshot.not']) def test_sdl_image_prepare_data(self): - # load an image file, get pixel data. Also O2 coverage for --preload-file + # load an image file, get pixel data. shutil.copyfile(path_from_root('tests', 'screenshot.jpg'), os.path.join(self.get_dir(), 'screenshot.not')) self.btest('sdl_image_prepare_data.c', reference='screenshot.jpg', args=['--preload-file', 'screenshot.not']) @@ -10080,56 +10339,56 @@ elif 'browser' in str(sys.argv): # SDL, OpenGL, textures, immediate mode. Closure for more coverage shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.reftest(path_from_root('tests', 'screenshot-gray-purple.png')) - Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_ogl.c'), '-O2', '--minify', '0', '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_ogl.c'), '-O2', '--minify', '0', '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png', '-s', 'GL_TESTING=1']).communicate() self.run_browser('something.html', 'You should see an image with gray at the top.', '/report_result?0') def test_sdl_ogl_defaultmatrixmode(self): # SDL, OpenGL, textures, immediate mode. Closure for more coverage shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.reftest(path_from_root('tests', 'screenshot-gray-purple.png')) - Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_ogl_defaultMatrixMode.c'), '--minify', '0', '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_ogl_defaultMatrixMode.c'), '--minify', '0', '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png', '-s', 'GL_TESTING=1']).communicate() self.run_browser('something.html', 'You should see an image with gray at the top.', '/report_result?0') def test_sdl_ogl_p(self): # Immediate mode with pointers shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.reftest(path_from_root('tests', 'screenshot-gray.png')) - Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_ogl_p.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_ogl_p.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png', '-s', 'GL_TESTING=1']).communicate() self.run_browser('something.html', 'You should see an image with gray at the top.', '/report_result?0') def test_sdl_fog_simple(self): # SDL, OpenGL, textures, fog, immediate mode. Closure for more coverage shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.reftest(path_from_root('tests', 'screenshot-fog-simple.png')) - Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_simple.c'), '-O2', '--minify', '0', '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_simple.c'), '-O2', '--minify', '0', '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png', '-s', 'GL_TESTING=1']).communicate() self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0') def test_sdl_fog_negative(self): # SDL, OpenGL, textures, fog, immediate mode. Closure for more coverage shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.reftest(path_from_root('tests', 'screenshot-fog-negative.png')) - Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_negative.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_negative.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png', '-s', 'GL_TESTING=1']).communicate() self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0') def test_sdl_fog_density(self): # SDL, OpenGL, textures, fog, immediate mode. Closure for more coverage shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.reftest(path_from_root('tests', 'screenshot-fog-density.png')) - Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_density.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_density.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png', '-s', 'GL_TESTING=1']).communicate() self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0') def test_sdl_fog_exp2(self): # SDL, OpenGL, textures, fog, immediate mode. Closure for more coverage shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.reftest(path_from_root('tests', 'screenshot-fog-exp2.png')) - Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_exp2.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_exp2.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png', '-s', 'GL_TESTING=1']).communicate() self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0') def test_sdl_fog_linear(self): # SDL, OpenGL, textures, fog, immediate mode. Closure for more coverage shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) self.reftest(path_from_root('tests', 'screenshot-fog-linear.png')) - Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_linear.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png']).communicate() + Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_linear.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png', '-s', 'GL_TESTING=1']).communicate() self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0') def test_worker(self): @@ -10269,26 +10528,26 @@ elif 'browser' in str(sys.argv): def test_glgears(self): self.reftest(path_from_root('tests', 'gears.png')) Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html', - '-DHAVE_BUILTIN_SINCOS', '--pre-js', 'reftest.js']).communicate() + '-DHAVE_BUILTIN_SINCOS', '--pre-js', 'reftest.js', '-s', 'GL_TESTING=1']).communicate() self.run_browser('something.html', 'You should see animating gears.', '/report_result?0') def test_glgears_animation(self): Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html', - '-DHAVE_BUILTIN_SINCOS', + '-DHAVE_BUILTIN_SINCOS', '-s', 'GL_TESTING=1', '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')]).communicate() self.run_browser('something.html', 'You should see animating gears.', '/report_gl_result?true') def test_glgears_bad(self): # Make sure that OpenGL ES is not available if typed arrays are not used Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles.c'), '-o', 'something.html', - '-DHAVE_BUILTIN_SINCOS', + '-DHAVE_BUILTIN_SINCOS', '-s', 'GL_TESTING=1', '-s', 'USE_TYPED_ARRAYS=0', '--shell-file', path_from_root('tests', 'hello_world_gles_shell.html')]).communicate() self.run_browser('something.html', 'You should not see animating gears.', '/report_gl_result?false') def test_glgears_deriv(self): self.reftest(path_from_root('tests', 'gears.png')) - Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles_deriv.c'), '-o', 'something.html', + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles_deriv.c'), '-o', 'something.html', '-s', 'GL_TESTING=1', '-DHAVE_BUILTIN_SINCOS', '--pre-js', 'reftest.js']).communicate() self.run_browser('something.html', 'You should see animating gears.', '/report_result?0') src = open('something.html').read() @@ -10319,7 +10578,7 @@ elif 'browser' in str(sys.argv): args = ['--preload-file', 'smoke.tga', '-O2'] # test optimizations and closure here as well for more coverage self.reftest(book_path(basename.replace('.bc', '.png'))) - Popen([PYTHON, EMCC, program, '-o', 'program.html', '--pre-js', 'reftest.js'] + args).communicate() + Popen([PYTHON, EMCC, program, '-o', 'program.html', '--pre-js', 'reftest.js', '-s', 'GL_TESTING=1'] + args).communicate() self.run_browser('program.html', '', '/report_result?0') def btest(self, filename, expected=None, reference=None, reference_slack=0, args=[]): # TODO: use in all other tests @@ -10334,7 +10593,7 @@ elif 'browser' in str(sys.argv): expected = [str(i) for i in range(0, reference_slack+1)] shutil.copyfile(path_from_root('tests', filename), os.path.join(self.get_dir(), filename)) self.reftest(path_from_root('tests', reference)) - args = args + ['--pre-js', 'reftest.js'] + args = args + ['--pre-js', 'reftest.js', '-s', 'GL_TESTING=1'] Popen([PYTHON, EMCC, os.path.join(self.get_dir(), filename), '-o', 'test.html'] + args).communicate() if type(expected) is str: expected = [expected] self.run_browser('test.html', '.', ['/report_result?' + e for e in expected]) @@ -10369,6 +10628,19 @@ 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.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png']) + def test_gl_ps_packed(self): + # packed data that needs to be strided + 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_matrix_identity(self): self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840']) @@ -10417,6 +10689,15 @@ elif 'browser' in str(sys.argv): def test_cubegeom_fog(self): self.btest('cubegeom_fog.c', expected=['1617140399', '-898782526', '-946179526']) + def test_cubegeom_pre_vao(self): + self.btest('cubegeom_pre_vao.c', expected=['-1472804742', '-1626058463', '-2046234971']) + + def test_cubegeom_pre2_vao(self): + self.btest('cubegeom_pre2_vao.c', expected=['-1472804742', '-1626058463', '-2046234971']) + + def test_cubegeom_pre2_vao2(self): + self.btest('cubegeom_pre2_vao2.c', expected=['-790445118']) + def test_cube_explosion(self): self.btest('cube_explosion.c', expected=['667220544', '-1543354600', '-1485258415']) @@ -10499,14 +10780,17 @@ elif 'browser' in str(sys.argv): def test_subdata(self): self.btest('gl_subdata.cpp', reference='float_tex.png') + def test_perspective(self): + self.btest('perspective.c', reference='perspective.png') + def test_runtimelink(self): main, supp = self.setup_runtimelink_test() open(self.in_dir('supp.cpp'), 'w').write(supp) - Popen([PYTHON, EMCC, self.in_dir('supp.cpp'), '-o', 'supp.js', '-s', 'LINKABLE=1', '-s', 'NAMED_GLOBALS=1', '-s', 'BUILD_AS_SHARED_LIB=2', '-O2', '--closure', '0']).communicate() + Popen([PYTHON, EMCC, self.in_dir('supp.cpp'), '-o', 'supp.js', '-s', 'LINKABLE=1', '-s', 'NAMED_GLOBALS=1', '-s', 'BUILD_AS_SHARED_LIB=2', '-O2']).communicate() shutil.move(self.in_dir('supp.js'), self.in_dir('supp.so')) - self.btest(main, args=['-s', 'LINKABLE=1', '-s', 'NAMED_GLOBALS=1', '-s', 'RUNTIME_LINKED_LIBS=["supp.so"]', '-DBROWSER=1', '-O2', '--closure', '0'], expected='76') + self.btest(main, args=['-s', 'LINKABLE=1', '-s', 'NAMED_GLOBALS=1', '-s', 'RUNTIME_LINKED_LIBS=["supp.so"]', '-DBROWSER=1', '-O2'], expected='76') def test_pre_run_deps(self): # Adding a dependency in preRun will delay run @@ -10802,12 +11086,15 @@ elif 'benchmark' in str(sys.argv): try_delete(final_filename) output = Popen([PYTHON, EMCC, filename, #'-O3', - '-O2', '-s', 'INLINING_LIMIT=0', '-s', 'DOUBLE_MODE=0', '-s', 'PRECISE_I64_MATH=0', - '-s', 'ASM_JS=1',# '-s', 'USE_MATH_IMUL=1', + '-O2', '-s', 'INLINING_LIMIT=0', '-s', 'DOUBLE_MODE=0', '-s', 'PRECISE_I64_MATH=0',# '-s', 'EXPLICIT_ZEXT=1', + '-s', 'ASM_JS=1', '-s', 'USE_MATH_IMUL=1', '-s', 'TOTAL_MEMORY=128*1024*1024', '-s', 'FAST_MEMORY=10*1024*1024', '-o', final_filename] + shared_args + emcc_args, stdout=PIPE, stderr=self.stderr_redirect).communicate() assert os.path.exists(final_filename), 'Failed to compile file: ' + output[0] + if self.save_JS: + self.hardcode_arguments(final_filename, args) + # Run JS global total_times, tests_done times = [] @@ -11060,7 +11347,7 @@ elif 'benchmark' in str(sys.argv): def test_dlmalloc(self): # XXX This seems to have regressed slightly with emcc. Are -g and the signs lines passed properly? src = open(path_from_root('system', 'lib', 'dlmalloc.c'), 'r').read() + '\n\n\n' + open(path_from_root('tests', 'dlmalloc_test.c'), 'r').read() - self.do_benchmark('dlmalloc', src, ['400', '3000'], '*3000,0*', emcc_args=['-g', '-s', 'CORRECT_SIGNS=2', '-s', 'CORRECT_SIGNS_LINES=[4820, 4195, 4250, 4203, 4209, 4239, 4231]']) + self.do_benchmark('dlmalloc', src, ['400', '3000'], '*3000,0*') def test_zlib(self): src = open(path_from_root('tests', 'zlib', 'benchmark.c'), 'r').read() @@ -11220,12 +11507,12 @@ elif 'sanity' in str(sys.argv): f = open(CONFIG_FILE, 'a') f.write('CLOSURE_COMPILER = "/tmp/nowhere/nothingtoseehere/kjadsfkjwelkjsdfkqgas/nonexistent.txt"\n') f.close() - output = self.check_working([EMCC, '-O2', 'tests/hello_world.cpp'], CLOSURE_FATAL) + output = self.check_working([EMCC, '-O2', '--closure', '1', 'tests/hello_world.cpp'], CLOSURE_FATAL) # With a working path, all is well restore() try_delete('a.out.js') - output = self.check_working([EMCC, '-O2', 'tests/hello_world.cpp'], '') + output = self.check_working([EMCC, '-O2', '--closure', '1', 'tests/hello_world.cpp'], '') assert os.path.exists('a.out.js') def test_llvm(self): @@ -11427,7 +11714,7 @@ fi try_delete(basebc_name) # we might need to check this file later try_delete(dcebc_name) # we might need to check this file later for ll_name in ll_names: try_delete(ll_name) - output = self.do([EMCC, '-O' + str(i), '--closure', '0', '-s', 'RELOOP=0', '--llvm-lto', '0', path_from_root('tests', filename)]) + output = self.do([EMCC, '-O' + str(i), '-s', 'RELOOP=0', '--llvm-lto', '0', path_from_root('tests', filename)]) #print output assert INCLUDING_MESSAGE.replace('X', libname) in output if libname == 'libc': @@ -11475,7 +11762,7 @@ fi print >> sys.stderr, phase, i opt = min(i, 2) try_delete('a.out.js') - output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_loop.cpp'), '-O' + str(opt), '--closure', '0'], + output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_loop.cpp'), '-O' + str(opt)], stdout=PIPE, stderr=PIPE).communicate() self.assertContained('hello, world!', run_js('a.out.js')) output = '\n'.join(output) @@ -11530,12 +11817,12 @@ fi (['--jcache'], 'hello_libcxx.cpp', False, True, False, True, False, True, []), ([], 'hello_libcxx.cpp', False, False, False, False, False, False, []), # finally, build a file close to the previous, to see that some chunks are found in the cache and some not - (['--jcache'], 'hello_libcxx_mod1.cpp', False, True, True, True, True, False, []), # win on pre, mix on funcs, lose on jsfuncs + (['--jcache'], 'hello_libcxx_mod1.cpp', False, True, True, True, True, True, []), # win on pre, mix on funcs, mix on jsfuncs (['--jcache'], 'hello_libcxx_mod1.cpp', False, True, False, True, False, True, []), ]: print >> sys.stderr, args, input_file, expect_pre_save, expect_pre_load, expect_funcs_save, expect_funcs_load, expect_jsfuncs_save, expect_jsfuncs_load, expected self.clear() - out, err = Popen([PYTHON, EMCC, '-O2', '--closure', '0', path_from_root('tests', input_file)] + args, stdout=PIPE, stderr=PIPE).communicate() + out, err = Popen([PYTHON, EMCC, '-O2', path_from_root('tests', input_file)] + args, stdout=PIPE, stderr=PIPE).communicate() errtail = err.split('emcc invocation')[-1] self.assertContained('hello, world!', run_js('a.out.js'), errtail) assert (PRE_SAVE_MSG in err) == expect_pre_save, errtail diff --git a/tests/s3tc_crunch.png b/tests/s3tc_crunch.png Binary files differindex 3510b83b..067be7aa 100644 --- a/tests/s3tc_crunch.png +++ b/tests/s3tc_crunch.png diff --git a/tests/screenshot-fog-density.png b/tests/screenshot-fog-density.png Binary files differindex cd1f6f1b..60f0c9ef 100644 --- a/tests/screenshot-fog-density.png +++ b/tests/screenshot-fog-density.png diff --git a/tests/screenshot-fog-exp2.png b/tests/screenshot-fog-exp2.png Binary files differindex cd5e6a63..4737a536 100644 --- a/tests/screenshot-fog-exp2.png +++ b/tests/screenshot-fog-exp2.png diff --git a/tests/screenshot-fog-linear.png b/tests/screenshot-fog-linear.png Binary files differindex 57534566..747c0c25 100644 --- a/tests/screenshot-fog-linear.png +++ b/tests/screenshot-fog-linear.png diff --git a/tests/screenshot-fog-negative.png b/tests/screenshot-fog-negative.png Binary files differindex 5b18a201..747063c9 100644 --- a/tests/screenshot-fog-negative.png +++ b/tests/screenshot-fog-negative.png diff --git a/tests/screenshot-fog-simple.png b/tests/screenshot-fog-simple.png Binary files differindex 527768fc..7624076c 100644 --- a/tests/screenshot-fog-simple.png +++ b/tests/screenshot-fog-simple.png diff --git a/tests/screenshot-gray-purple.png b/tests/screenshot-gray-purple.png Binary files differindex 514b29a1..eaf08e6a 100644 --- a/tests/screenshot-gray-purple.png +++ b/tests/screenshot-gray-purple.png diff --git a/tests/screenshot-gray.png b/tests/screenshot-gray.png Binary files differindex 16e45a7a..af06c256 100644 --- a/tests/screenshot-gray.png +++ b/tests/screenshot-gray.png diff --git a/tests/sdl_gl_read.c b/tests/sdl_gl_read.c index 552eb8c0..d752f94d 100644 --- a/tests/sdl_gl_read.c +++ b/tests/sdl_gl_read.c @@ -6,6 +6,7 @@ #include <stdio.h> #include <stdlib.h> +#include <assert.h> GLuint programObject; int width = 512; @@ -118,8 +119,14 @@ void Draw () } void Verify() { - unsigned char *data = malloc(width*height*4); + unsigned char *data = malloc(width*height*4 + 16); + int *last = (int*)(data + width*height*4 - 4); + int *after = (int*)(data + width*height*4); + *last = 0xdeadbeef; + *after = 0x12345678; glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + assert(*last != 0xdeadbeef); // should overwrite the buffer to the end + assert(*after == 0x12345678); // nothing should be written afterwards! // Should see some blue, and nothing else int seen = 0; int ok = 1; diff --git a/tests/sdl_image_jpeg.c b/tests/sdl_image_jpeg.c new file mode 100644 index 00000000..10619dad --- /dev/null +++ b/tests/sdl_image_jpeg.c @@ -0,0 +1,45 @@ +#include <stdio.h> +#include <SDL/SDL.h> +#include <SDL/SDL_image.h> +#include <assert.h> +#include <emscripten.h> + +int testImage(SDL_Surface* screen, const char* fileName) { + SDL_Surface *image = IMG_Load(fileName); + if (!image) + { + printf("IMG_Load: %s\n", IMG_GetError()); + return 0; + } + assert(image->format->BitsPerPixel == 32); + assert(image->format->BytesPerPixel == 4); + assert(image->pitch == 4*image->w); + int result = image->w; + + SDL_BlitSurface (image, NULL, screen, NULL); + SDL_FreeSurface (image); + + return result; +} + +int main() { + SDL_Init(SDL_INIT_VIDEO); + SDL_Surface *screen = SDL_SetVideoMode(600, 450, 32, SDL_SWSURFACE); + + int result = 0; + result = testImage(screen, "screenshot.jpeg"); // relative path + assert(result != 0); + result |= testImage(screen, "/screenshot.jpeg"); // absolute path + assert(result != 0); + + SDL_Flip(screen); + + printf("you should see an image.\n"); + + SDL_Quit(); + + REPORT_RESULT(); + + return 0; +} + diff --git a/tests/websockets.c b/tests/websockets.c index 59acbd69..34aa44b4 100644 --- a/tests/websockets.c +++ b/tests/websockets.c @@ -82,7 +82,7 @@ void iter(void *arg) { printf("sum: %d\n", sum); #if EMSCRIPTEN - assert(not_always_data == 1); + //assert(not_always_data == 1); int result = sum; REPORT_RESULT(); |