void GLProgram::recover() { m_vertexShader = loadAndCompileShader(m_vShader, GL_VERTEX_SHADER); m_fragmentShader = loadAndCompileShader(m_fShader, GL_FRAGMENT_SHADER); if (m_vertexShader == 0 or m_fragmentShader == 0) { return; } m_programObject = glCreateProgram(); if (m_programObject == 0) { CHECK_GL_ERROR; return; } glAttachShader(m_programObject, m_vertexShader); glAttachShader(m_programObject, m_fragmentShader); for (const auto& it : m_attributes) { glBindAttribLocation(m_programObject, it.second->getPosition(), it.second->getName().c_str()); } linkProgram(); }
// ---------------------------------------------------------------------------- // Create Vertex Fragment program // ---------------------------------------------------------------------------- GLuint createVertexFragmentProgram(const std::string& vertex_shader_path, const std::string& fragment_shader_path) { GLuint vertShader = loadAndCompileShader(GL_VERTEX_SHADER, vertex_shader_path); GLuint fragShader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragment_shader_path); GLuint program = glCreateProgram(); if (!program) { throw std::runtime_error("Can't create GLSL program."); } glAttachShader(program, vertShader); glAttachShader(program, fragShader); glLinkProgram(program); GLint status; glGetProgramiv(program, GL_LINK_STATUS, &status); if (!status) { std::cerr << "Linking error in shader program!" << std::endl; GLint logLen; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLen); if (logLen > 0) { char *log = new char[logLen]; GLsizei written; glGetProgramInfoLog(program, logLen, &written, log); std::cerr << "Shader log: " << std::endl; std::cerr << log << std::endl; delete[] log; } throw std::runtime_error("Can't link shader program."); } return program; }
GLProgram* GLProgram::create(const char* vShader, const char* fShader) { auto vertexShader = loadAndCompileShader(vShader, GL_VERTEX_SHADER); auto fragmentShader = loadAndCompileShader(fShader, GL_FRAGMENT_SHADER); if (vertexShader == 0 or fragmentShader == 0) { LOGE("Failed to load and compile shaders"); return nullptr; } GLProgram* program = new (std::nothrow) GLProgram(); if (not program) { LOGE("Failed to create GLProgram"); return nullptr; } program->m_programObject = glCreateProgram(); if (program->m_programObject == 0) { CHECK_GL_ERROR; delete program; LOGE("Failed to create program object"); return nullptr; } glAttachShader(program->m_programObject, vertexShader); glAttachShader(program->m_programObject, fragmentShader); program->m_vertexShader = vertexShader; program->m_fragmentShader = fragmentShader; program->m_vShader = vShader; program->m_fShader = fShader; return program; }
static void readShader(GLuint shader, const char *filename) { const int max = 100*1000; int n; char *buffer = (char*) malloc(max); FILE *f = fopen(filename, "r"); if (!f) { fprintf(stderr, "Unable to open shader file %s\n", filename); exit(1); } n = fread(buffer, 1, max, f); printf("Read %d bytes from shader file %s\n", n, filename); if (n > 0) { buffer[n] = 0; loadAndCompileShader(shader, buffer); } fclose(f); free(buffer); }
bool API2Test::testShaderAttribs(void) { static const char *vertShaderText = "attribute vec4 generic; \n" "void main() { \n" " gl_Position = ftransform(); \n" " gl_FrontColor = generic; \n" "} \n"; GLuint vertShader, program; vertShader = loadAndCompileShader(GL_VERTEX_SHADER, vertShaderText); if (!vertShader) { return false; } program = createProgram(vertShader, 0); if (!program) { REPORT_FAILURE("glCreateProgram (uniform test) failed"); return false; } glUseProgram_func(program); static const GLfloat testColors[3][4] = { { 1.0, 0.5, 0.25, 0.0 }, { 0.0, 0.1, 0.2, 0.3 }, { 0.5, 0.6, 0.7, 0.8 }, }; // let compiler allocate the attribute location const GLint attr = glGetAttribLocation_func(program, "generic"); if (attr < 0) { REPORT_FAILURE("glGetAttribLocation failed"); return false; } for (int i = 0; i < 3; i++) { GLfloat pixel[4]; renderQuadWithArrays(attr, testColors[i], pixel); if (!equalColors(pixel, testColors[i])) { #if 0 printf("Expected color %f %f %f\n", testColors[i][0], testColors[i][1], testColors[i][2]); printf("Found color %f %f %f\n", pixel[0], pixel[1], pixel[2]); #endif REPORT_FAILURE("Vertex array test failed"); return false; } } // Test explicit attribute binding. const GLint bindAttr = 6; // XXX a non-colliding alias glBindAttribLocation_func(program, bindAttr, "generic"); glLinkProgram_func(program); GLint loc = glGetAttribLocation_func(program, "generic"); if (loc != bindAttr) { REPORT_FAILURE("glBindAttribLocation failed"); return false; } for (int i = 0; i < 3; i++) { GLfloat pixel[4]; renderQuadWithArrays(bindAttr, testColors[i], pixel); if (!equalColors(pixel, testColors[i])) { REPORT_FAILURE("Vertex array test failed (2)"); return false; } } return true; }
bool API2Test::testUniformiFuncs(void) { static const char *fragShaderText = "uniform int ui1; \n" "uniform ivec2 ui2; \n" "uniform ivec3 ui3; \n" "uniform ivec4 ui4; \n" "void main() { \n" " gl_FragColor = vec4(ui1, ui2.y, ui3.z, ui4.w) * 0.1; \n" "} \n"; GLuint fragShader, program; GLint ui1, ui2, ui3, ui4; fragShader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText); if (!fragShader) { return false; } program = createProgram(0, fragShader); if (!program) { REPORT_FAILURE("glCreateProgram (uniform test) failed"); return false; } glUseProgram_func(program); ui1 = glGetUniformLocation_func(program, "ui1"); if (ui1 < 0) { REPORT_FAILURE("glGetUniform \"ui1\" failed"); return false; } ui2 = glGetUniformLocation_func(program, "ui2"); if (ui2 < 0) { REPORT_FAILURE("glGetUniform \"ui2\" failed"); return false; } ui3 = glGetUniformLocation_func(program, "ui3"); if (ui3 < 0) { REPORT_FAILURE("glGetUniform \"ui3\" failed"); return false; } ui4 = glGetUniformLocation_func(program, "ui4"); if (ui4 < 0) { REPORT_FAILURE("glGetUniform \"ui4\" failed"); return false; } GLfloat pixel[4], expected[4]; GLint expectedInt[4]; // Test glUniform[1234]i() expectedInt[0] = 1; expectedInt[1] = 2; expectedInt[2] = 3; expectedInt[3] = 4; expected[0] = 0.1; expected[1] = 0.2; expected[2] = 0.3; expected[3] = 0.4; glUniform1i_func(ui1, expectedInt[0]); glUniform2i_func(ui2, 0, expectedInt[1]); glUniform3i_func(ui3, 0, 0, expectedInt[2]); glUniform4i_func(ui4, 0, 0, 0, expectedInt[3]); renderQuad(pixel); if (!equalColors(pixel, expected)) { REPORT_FAILURE("glUniform[1234]i failed"); //printf("%f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]); return false; } // Test glUniform[1234]iv() GLint u[4]; expectedInt[0] = 9; expectedInt[1] = 8; expectedInt[2] = 7; expectedInt[3] = 6; expected[0] = 0.9; expected[1] = 0.8; expected[2] = 0.7; expected[3] = 0.6; u[0] = expectedInt[0]; glUniform1iv_func(ui1, 1, u); u[0] = 0; u[1] = expectedInt[1]; glUniform2iv_func(ui2, 1, u); u[0] = 0; u[1] = 0; u[2] = expectedInt[2]; glUniform3iv_func(ui3, 1, u); u[0] = 0; u[1] = 0; u[2] = 0; u[3] = expectedInt[3]; glUniform4iv_func(ui4, 1, u); renderQuad(pixel); if (!equalColors(pixel, expected)) { REPORT_FAILURE("glUniform[1234]i failed"); #if 0 printf("Expected color %f %f %f %f\n", expected[0], expected[1], expected[2], expected[3]); printf("Found color %f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]); #endif return false; } return true; }
bool API2Test::testUniformfFuncs(void) { static const char *fragShaderText = "uniform float uf1; \n" "uniform vec2 uf2; \n" "uniform vec3 uf3; \n" "uniform vec4 uf4; \n" "void main() { \n" " gl_FragColor = vec4(uf1, uf2.y, uf3.z, uf4.w); \n" "} \n"; GLuint fragShader, program; GLint uf1, uf2, uf3, uf4; GLfloat value[4]; fragShader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText); if (!fragShader) { return false; } program = createProgram(0, fragShader); if (!program) { REPORT_FAILURE("glCreateProgram (uniform test) failed"); return false; } glUseProgram_func(program); uf1 = glGetUniformLocation_func(program, "uf1"); if (uf1 < 0) { REPORT_FAILURE("glGetUniform \"uf1\" failed"); return false; } uf2 = glGetUniformLocation_func(program, "uf2"); if (uf2 < 0) { REPORT_FAILURE("glGetUniform \"uf2\" failed"); return false; } uf3 = glGetUniformLocation_func(program, "uf3"); if (uf3 < 0) { REPORT_FAILURE("glGetUniform \"uf3\" failed"); return false; } uf4 = glGetUniformLocation_func(program, "uf4"); if (uf4 < 0) { REPORT_FAILURE("glGetUniform \"uf4\" failed"); return false; } GLfloat pixel[4], expected[4]; // Test glUniform[1234]f() expected[0] = 0.1; expected[1] = 0.2; expected[2] = 0.3; expected[3] = 0.4; glUniform1f_func(uf1, expected[0]); glUniform2f_func(uf2, 0.0, expected[1]); glUniform3f_func(uf3, 0.0, 0.0, expected[2]); glUniform4f_func(uf4, 0.0, 0.0, 0.0, expected[3]); renderQuad(pixel); if (!equalColors(pixel, expected)) { REPORT_FAILURE("glUniform[1234]f failed"); //printf("found: %f %f %f %f\n", pixel[0], pixel[1], pixel[2], pixel[3]); //printf("expected: %f %f %f %f\n", expected[0], expected[1], expected[2], expected[3]); return false; } // Test glUniform[1234]fv() GLfloat u[4]; expected[0] = 0.9; expected[1] = 0.8; expected[2] = 0.7; expected[3] = 0.6; u[0] = expected[0]; glUniform1fv_func(uf1, 1, u); u[0] = 0.0; u[1] = expected[1]; glUniform2fv_func(uf2, 1, u); u[0] = 0.0; u[1] = 0.0; u[2] = expected[2]; glUniform3fv_func(uf3, 1, u); u[0] = 0.0; u[1] = 0.0; u[2] = 0.0; u[3] = expected[3]; glUniform4fv_func(uf4, 1, u); renderQuad(pixel); if (!equalColors(pixel, expected)) { REPORT_FAILURE("glUniform[1234]f failed"); return false; } // Test glGetUniformfv glUniform4fv_func(uf4, 1, expected); glGetUniformfv_func(program, uf4, value); if (value[0] != expected[0] || value[1] != expected[1] || value[2] != expected[2] || value[3] != expected[3]) { REPORT_FAILURE("glGetUniformfv failed"); return false; } return true; }
bool API2Test::testShaderObjectFuncs(void) { static const char *vertShaderText = "void main() { \n" " gl_Position = ftransform(); \n" "} \n"; static const char *fragShaderText = "void main() { \n" " gl_FragColor = vec4(1.0, 0.5, 0.25, 0.0); \n" "} \n"; GLuint vertShader, fragShader, program; GLint stat, val, err; vertShader = loadAndCompileShader(GL_VERTEX_SHADER, vertShaderText); if (!vertShader) return false; fragShader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText); if (!fragShader) return false; program = createProgram(vertShader, fragShader); if (!program) { REPORT_FAILURE("glCreateProgram failed"); return false; } glGetProgramiv_func(program, GL_LINK_STATUS, &stat); if (!stat) { REPORT_FAILURE("glLinkProgram failed"); return false; } glUseProgram_func(program); glGetIntegerv(GL_CURRENT_PROGRAM, &val); if (val != (GLint) program) { REPORT_FAILURE("glGetInteger(GL_CURRENT_PROGRAM) failed"); return false; } err = glGetError(); if (err) { REPORT_FAILURE("OpenGL error detected in testShaderFuncs"); return false; } if (!glIsProgram_func(program)) { REPORT_FAILURE("glIsProgram failed"); return false; } GLuint objects[2]; GLsizei count; glGetProgramiv_func(program, GL_ATTACHED_SHADERS, &val); if (val != 2) { REPORT_FAILURE("glGetProgramiv(GL_ATTACHED_SHADERS) failed"); return false; } glGetAttachedShaders_func(program, 2, &count, objects); if (count != 2) { REPORT_FAILURE("glGetAttachedShaders failed (wrong count)"); return false; } if (objects[0] != vertShader && objects[1] != vertShader) { REPORT_FAILURE("glGetAttachedShaders failed (vertex shader missing)"); return false; } if (objects[0] != fragShader && objects[1] != fragShader) { REPORT_FAILURE("glGetAttachedShaders failed (fragment shader missing)"); return false; } glValidateProgram_func(program); glGetProgramiv_func(program, GL_VALIDATE_STATUS, &stat); if (!stat) { REPORT_FAILURE("glValidateProgram failed"); return false; } // Delete vertex shader glDeleteShader_func(vertShader); if (!glIsShader_func(vertShader)) { // the shader is still attached so the handle should be valid REPORT_FAILURE("glIsShader(deleted shader) failed"); return false; } glGetShaderiv_func(vertShader, GL_DELETE_STATUS, &stat); if (stat != GL_TRUE) { REPORT_FAILURE("Incorrect shader delete status"); return false; } // Delete fragment shader glDeleteShader_func(fragShader); // Delete program object glDeleteProgram_func(program); if (!glIsProgram_func(program)) { // the program is still in use so the handle should be valid REPORT_FAILURE("glIsProgram(deleted program) failed"); return false; } glGetProgramiv_func(program, GL_DELETE_STATUS, &stat); if (stat != GL_TRUE) { REPORT_FAILURE("Incorrect program delete status"); return false; } // now unbind the program glUseProgram_func(0); stat = glIsProgram_func(program); if (stat) { // the program and handle should have really been deleted now REPORT_FAILURE("glIsProgram(deleted program) failed"); return false; } glGetProgramiv_func(program, GL_DELETE_STATUS, &stat); err = glGetError(); if (!err) { // the program and handle should have been deleted now // so glGetProgramiv() should have generated an error REPORT_FAILURE("glGetProgramiv(deleted program) failed"); return false; } return true; }