#include "SDL/SDL_opengl.h" #include "SDL/SDL.h" #include #include #include #include void RunTest(int testVariant) { GLuint vs = 0; const char *vsCode = "#version 100\n" "attribute vec4 pos; void main() { gl_Position = pos; }"; vs = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs, 1, &vsCode, NULL); glCompileShader(vs); GLuint ps = 0; const char *psCode = "#version 100\n" "precision lowp float;\n" "uniform vec3 color;\n" "uniform vec3 colors[3];\n" "void main() { gl_FragColor = vec4(color,1) + vec4(colors[0].r, colors[1].g, colors[2].b, 1); }"; ps = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(ps, 1, &psCode, NULL); glCompileShader(ps); GLuint program = 0; program = glCreateProgram(); glAttachShader(program, vs); glAttachShader(program, ps); glBindAttribLocation(program, 0, "pos"); glLinkProgram(program); // Also test that GL_ACTIVE_ATTRIBUTE_MAX_LENGTH and GL_ACTIVE_UNIFORM_MAX_LENGTH work. See https://github.com/kripken/emscripten/issues/1796. GLint param; glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, ¶m); printf("active attrib max length: %d\n", param); assert(param == 4); // "pos"+null terminator glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, ¶m); printf("active uniform max length: %d\n", param); assert(param == 10); // "colors[0]"+null terminator int color_loc = glGetUniformLocation(program, "color"); assert(color_loc != -1); glUseProgram(program); float col[3] = { 0.2f, 0.2f, 0.2f }; glUniform3fv(color_loc, 1, col); int loc = glGetUniformLocation(program, "colors"); assert(loc != -1); // In previous Emscripten GL layer code, calling glGetUniformLocation would do extra caching operations that interacts how glUniform** after that will work, // so to exhibit extra issues in old code (and to keep new code from regressing), must test both with and without excess glGetUniformLocation calls. if ((testVariant&1) != 0) { printf("check glGetUniformLocation with indexes\n"); // Deliberately check in odd order to make sure any kind of lazy operations won't affect the indices we get. assert(glGetUniformLocation(program, "colors[2]") == loc+2); assert(glGetUniformLocation(program, "colors[0]") == loc); assert(glGetUniformLocation(program, "colors[3]") == -1); assert(glGetUniformLocation(program, "colors[1]") == loc+1); assert(glGetUniformLocation(program, "colors[]") == loc); assert(glGetUniformLocation(program, "colors[-100]") == -1); assert(glGetUniformLocation(program, "colors[bleh]") == -1); printf(" ...ok\n"); } float colors[4*3] = { 1,0,0, 0,0.5,0, 0,0,0.2, 1,1,1 }; if ((testVariant&2)!=0) { glUniform3fv(loc+1, 3, colors+3); // Pass the actual colors (testing a nonzero location offset), but do a mistake by setting one index too many. Spec says this should be gracefully handled, and that excess elements are ignored. assert(glGetError() == GL_NO_ERROR); glUniform3fv(loc, 1, colors); // Set the first index as well. assert(glGetError() == GL_NO_ERROR); } else { glUniform3fv(loc, 4, colors); // Just directly set the full array. assert(glGetError() == GL_NO_ERROR); } assert(glGetError() == GL_NO_ERROR); GLuint vbo = 0; const GLfloat v[] = { -1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1 }; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), 0); glEnableVertexAttribArray(0); glDrawArrays(GL_TRIANGLES, 0, 6); int in_worker = EM_ASM_INT_V({ return typeof importScripts !== 'undefined' }); if (!in_worker) { printf("Doing readpixels check\n"); unsigned char pixel[4]; glReadPixels(1,1,1,1,GL_RGBA,GL_UNSIGNED_BYTE, pixel); //printf("%d,%d,%d,%d\n", pixel[0], pixel[1], pixel[2], pixel[3]); assert(pixel[0] == 255); assert(pixel[1] == 178); assert(pixel[2] == 102); assert(pixel[3] == 255); } printf("OK: Case %d passed.\n", testVariant); // Lazy, don't clean up afterwards. } 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; } screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed* if ( !screen ) { printf("Unable to set video mode: %s\n", SDL_GetError()); return 1; } for(int i = 0; i < 4; ++i) RunTest(i); #ifdef REPORT_RESULT int result = 1; REPORT_RESULT(); #endif return 0; }