summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/aniso.pngbin35041 -> 26812 bytes
-rw-r--r--tests/cubegeom.c14
-rw-r--r--tests/cubegeom_pre2_vao.c380
-rw-r--r--tests/cubegeom_pre2_vao2.c381
-rw-r--r--tests/cubegeom_pre_vao.c333
-rw-r--r--tests/float_tex.pngbin19944 -> 18869 bytes
-rw-r--r--tests/fuzz/1.c117
-rw-r--r--tests/fuzz/1.c.txt1
-rwxr-xr-xtests/fuzz/creduce_tester.py53
-rw-r--r--tests/fuzz/csmith.h130
-rwxr-xr-xtests/fuzz/csmith_driver.py100
-rw-r--r--tests/fuzz/platform_generic.h132
-rw-r--r--tests/fuzz/random_inc.h129
-rw-r--r--tests/fuzz/safe_math.h947
-rw-r--r--tests/gears.pngbin7832 -> 6407 bytes
-rw-r--r--tests/gl_ps.c3
-rw-r--r--tests/gl_ps.pngbin203535 -> 202598 bytes
-rw-r--r--tests/gl_ps_packed.c230
-rw-r--r--tests/gl_ps_workaround.c230
-rw-r--r--tests/gl_ps_workaround2.c230
-rw-r--r--tests/glbook/CH13_ParticleSystem.pngbin5106 -> 4921 bytes
-rw-r--r--tests/perspective.c408
-rw-r--r--tests/perspective.pngbin0 -> 2477 bytes
-rwxr-xr-xtests/runner.py499
-rw-r--r--tests/s3tc_crunch.pngbin353677 -> 271258 bytes
-rw-r--r--tests/screenshot-fog-density.pngbin154012 -> 157048 bytes
-rw-r--r--tests/screenshot-fog-exp2.pngbin119847 -> 122164 bytes
-rw-r--r--tests/screenshot-fog-linear.pngbin247928 -> 250343 bytes
-rw-r--r--tests/screenshot-fog-negative.pngbin79537 -> 80704 bytes
-rw-r--r--tests/screenshot-fog-simple.pngbin36557 -> 37940 bytes
-rw-r--r--tests/screenshot-gray-purple.pngbin242425 -> 241235 bytes
-rw-r--r--tests/screenshot-gray.pngbin203336 -> 202044 bytes
-rw-r--r--tests/sdl_gl_read.c9
-rw-r--r--tests/sdl_image_jpeg.c45
-rw-r--r--tests/websockets.c2
35 files changed, 4265 insertions, 108 deletions
diff --git a/tests/aniso.png b/tests/aniso.png
index 5f5812d2..2bcb2f5f 100644
--- a/tests/aniso.png
+++ b/tests/aniso.png
Binary files differ
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
index 8c3c6502..8fc005ff 100644
--- a/tests/float_tex.png
+++ b/tests/float_tex.png
Binary files differ
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
index ffb855c4..a35db625 100644
--- a/tests/gears.png
+++ b/tests/gears.png
Binary files differ
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
index 185f7166..ac13ec0b 100644
--- a/tests/gl_ps.png
+++ b/tests/gl_ps.png
Binary files differ
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
index ff9c3496..4b69414f 100644
--- a/tests/glbook/CH13_ParticleSystem.png
+++ b/tests/glbook/CH13_ParticleSystem.png
Binary files differ
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
new file mode 100644
index 00000000..04cedc71
--- /dev/null
+++ b/tests/perspective.png
Binary files differ
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
index 3510b83b..067be7aa 100644
--- a/tests/s3tc_crunch.png
+++ b/tests/s3tc_crunch.png
Binary files differ
diff --git a/tests/screenshot-fog-density.png b/tests/screenshot-fog-density.png
index cd1f6f1b..60f0c9ef 100644
--- a/tests/screenshot-fog-density.png
+++ b/tests/screenshot-fog-density.png
Binary files differ
diff --git a/tests/screenshot-fog-exp2.png b/tests/screenshot-fog-exp2.png
index cd5e6a63..4737a536 100644
--- a/tests/screenshot-fog-exp2.png
+++ b/tests/screenshot-fog-exp2.png
Binary files differ
diff --git a/tests/screenshot-fog-linear.png b/tests/screenshot-fog-linear.png
index 57534566..747c0c25 100644
--- a/tests/screenshot-fog-linear.png
+++ b/tests/screenshot-fog-linear.png
Binary files differ
diff --git a/tests/screenshot-fog-negative.png b/tests/screenshot-fog-negative.png
index 5b18a201..747063c9 100644
--- a/tests/screenshot-fog-negative.png
+++ b/tests/screenshot-fog-negative.png
Binary files differ
diff --git a/tests/screenshot-fog-simple.png b/tests/screenshot-fog-simple.png
index 527768fc..7624076c 100644
--- a/tests/screenshot-fog-simple.png
+++ b/tests/screenshot-fog-simple.png
Binary files differ
diff --git a/tests/screenshot-gray-purple.png b/tests/screenshot-gray-purple.png
index 514b29a1..eaf08e6a 100644
--- a/tests/screenshot-gray-purple.png
+++ b/tests/screenshot-gray-purple.png
Binary files differ
diff --git a/tests/screenshot-gray.png b/tests/screenshot-gray.png
index 16e45a7a..af06c256 100644
--- a/tests/screenshot-gray.png
+++ b/tests/screenshot-gray.png
Binary files differ
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();