GrGLuint GrGLProgram::CompileShader(GrGLenum type, int stringCnt, const char** strings, int* stringLengths) { GrGLuint shader = GR_GL(CreateShader(type)); if (0 == shader) { return 0; } GrGLint compiled = GR_GL_INIT_ZERO; GR_GL(ShaderSource(shader, stringCnt, strings, stringLengths)); GR_GL(CompileShader(shader)); GR_GL(GetShaderiv(shader, GR_GL_COMPILE_STATUS, &compiled)); if (!compiled) { GrGLint infoLen = GR_GL_INIT_ZERO; GR_GL(GetShaderiv(shader, GR_GL_INFO_LOG_LENGTH, &infoLen)); GrAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { GR_GL(GetShaderInfoLog(shader, infoLen+1, NULL, (char*)log.get())); for (int i = 0; i < stringCnt; ++i) { if (NULL == stringLengths || stringLengths[i] < 0) { GrPrintf(strings[i]); } else { GrPrintf("%.*s", stringLengths[i], strings[i]); } } GrPrintf("\n%s", log.get()); } GrAssert(!"Shader compilation failed!"); GR_GL(DeleteShader(shader)); return 0; } return shader; }
// Compiles a GL shader and attaches it to a program. Returns the shader ID if // successful, or 0 if not. static GrGLuint attach_shader(const GrGLContext& glCtx, GrGLuint programId, GrGLenum type, const SkString& shaderSrc) { const GrGLInterface* gli = glCtx.interface(); GrGLuint shaderId; GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); if (0 == shaderId) { return 0; } const GrGLchar* sourceStr = shaderSrc.c_str(); GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); GR_GL_CALL(gli, CompileShader(shaderId)); // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. bool checkCompiled = !glCtx.isChromium(); #ifdef SK_DEBUG checkCompiled = true; #endif if (checkCompiled) { GrGLint compiled = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); if (!compiled) { GrGLint infoLen = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { // retrieve length even though we don't need it to workaround bug in Chromium cmd // buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get())); GrPrintf(shaderSrc.c_str()); GrPrintf("\n%s", log.get()); } SkDEBUGFAIL("Shader compilation failed!"); GR_GL_CALL(gli, DeleteShader(shaderId)); return 0; } } TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("skia.gpu"), "skia_gpu::GLShader", TRACE_EVENT_SCOPE_THREAD, "shader", TRACE_STR_COPY(shaderSrc.c_str())); if (c_PrintShaders) { GrPrintf(shaderSrc.c_str()); GrPrintf("\n"); } // Attach the shader, but defer deletion until after we have linked the program. // This works around a bug in the Android emulator's GLES2 wrapper which // will immediately delete the shader object and free its memory even though it's // attached to a program, which then causes glLinkProgram to fail. GR_GL_CALL(gli, AttachShader(programId, shaderId)); return shaderId; }
inline GLuint CreateProgram(LPCSTR vsrc, LPCSTR fsrc) { const GLuint vobj = glCreateShader(GL_VERTEX_SHADER); if (!vobj) return 0; glShaderSource(vobj, 1, &vsrc, 0); glCompileShader(vobj); if (GetShaderInfoLog(vobj) == 0) { glDeleteShader(vobj); return 0; } const GLuint fobj = glCreateShader(GL_FRAGMENT_SHADER); if (!fobj) { glDeleteShader(vobj); return 0; } glShaderSource(fobj, 1, &fsrc, 0); glCompileShader(fobj); if (GetShaderInfoLog(fobj) == 0) { glDeleteShader(vobj); glDeleteShader(fobj); return 0; } GLuint program = glCreateProgram(); if (program) { glAttachShader(program, vobj); glAttachShader(program, fobj); glLinkProgram(program); if (GetProgramInfoLog(program) == 0) { glDetachShader(program, fobj); glDetachShader(program, vobj); glDeleteProgram(program); program = 0; } } glDeleteShader(vobj); glDeleteShader(fobj); return program; }
void linkShaderProgram(GLuint shaderProgram) { glLinkProgram(shaderProgram); GLint linkOk = 0; glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linkOk); if (!linkOk) { std::string err = GetShaderInfoLog(shaderProgram); fatal_error(err); return; } }
// Compiles a GL shader, attaches it to a program, and releases the shader's reference. // (That way there's no need to hang on to the GL shader id and delete it later.) static bool attach_shader(const GrGLContext& glCtx, GrGLuint programId, GrGLenum type, const SkString& shaderSrc) { const GrGLInterface* gli = glCtx.interface(); GrGLuint shaderId; GR_GL_CALL_RET(gli, shaderId, CreateShader(type)); if (0 == shaderId) { return false; } const GrGLchar* sourceStr = shaderSrc.c_str(); GrGLint sourceLength = static_cast<GrGLint>(shaderSrc.size()); GR_GL_CALL(gli, ShaderSource(shaderId, 1, &sourceStr, &sourceLength)); GR_GL_CALL(gli, CompileShader(shaderId)); // Calling GetShaderiv in Chromium is quite expensive. Assume success in release builds. bool checkCompiled = !glCtx.info().isChromium(); #ifdef SK_DEBUG checkCompiled = true; #endif if (checkCompiled) { GrGLint compiled = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_COMPILE_STATUS, &compiled)); if (!compiled) { GrGLint infoLen = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderiv(shaderId, GR_GL_INFO_LOG_LENGTH, &infoLen)); SkAutoMalloc log(sizeof(char)*(infoLen+1)); // outside if for debugger if (infoLen > 0) { // retrieve length even though we don't need it to workaround bug in Chromium cmd // buffer param validation. GrGLsizei length = GR_GL_INIT_ZERO; GR_GL_CALL(gli, GetShaderInfoLog(shaderId, infoLen+1, &length, (char*)log.get())); GrPrintf(shaderSrc.c_str()); GrPrintf("\n%s", log.get()); } SkDEBUGFAIL("Shader compilation failed!"); GR_GL_CALL(gli, DeleteShader(shaderId)); return false; } } if (c_PrintShaders) { GrPrintf(shaderSrc.c_str()); GrPrintf("\n"); } GR_GL_CALL(gli, AttachShader(programId, shaderId)); GR_GL_CALL(gli, DeleteShader(shaderId)); return true; }
bool CompileShaderText(GLuint *shader, GLenum shaderType, const char *text) { GLint stat; *shader = CreateShader(shaderType); ShaderSource(*shader, 1, (const GLchar **)&text, NULL); CompileShader(*shader); GetShaderiv(*shader, GL_COMPILE_STATUS, &stat); if (!stat) { GLchar log[1000]; GLsizei len; GetShaderInfoLog(*shader, 1000, &len, log); wxLogError(wxT("BR24radar_pi: problem compiling shader: %s"), log); return false; } return true; }
static GrGLuint load_shader(const GrGLInterface* gl, const char* shaderSrc, GrGLenum type) { GrGLuint shader; // Create the shader object GR_GL_CALL_RET(gl, shader, CreateShader(type)); // Load the shader source GR_GL_CALL(gl, ShaderSource(shader, 1, &shaderSrc, NULL)); // Compile the shader GR_GL_CALL(gl, CompileShader(shader)); // Check for compile time errors GrGLint success; GrGLchar infoLog[512]; GR_GL_CALL(gl, GetShaderiv(shader, GR_GL_COMPILE_STATUS, &success)); if (!success) { GR_GL_CALL(gl, GetShaderInfoLog(shader, 512, NULL, infoLog)); SkDebugf("ERROR::SHADER::COMPLIATION_FAILED: %s\n", infoLog); } return shader; }
GLuint OpenGLInterface::LoadShader(const char* filename, GLenum shader_type, bool check_errors) { GLuint result = 0; // Attempt to open the given file by name std::ifstream t(filename); // Test if the file open step was successful if ((t.rdstate() & std::ifstream::failbit) == 0) { std::string str; // Determine the size of the file and preallocate the size of the string we will be reading into t.seekg(0, std::ios::end); str.reserve((size_t)t.tellg()); t.seekg(0, std::ios::beg); // Read the entire file's contents into the string str.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>()); // Create an empty shader of the given type // The valid types are: // GL_COMPUTE_SHADER // GL_VERTEX_SHADER // GL_TESS_CONTROL_SHADER // GL_TESS_EVALUATION_SHADER // GL_GEOMETRY_SHADER // GL_FRAGMENT_SHADER // Returns zero unpon failure result = CreateShader(shader_type); if (result) { const char* data = str.c_str(); ShaderSource(result, 1, &data, NULL); CompileShader(result); if (check_errors) { GLint status = 0; GetObjectParameterivARB(result, GL_COMPILE_STATUS, &status); if (!status) { char buffer[4096]; GetShaderInfoLog(result, 4096, NULL, buffer); OutputDebugStringA(filename); OutputDebugStringA(":"); OutputDebugStringA(buffer); OutputDebugStringA("\n"); DeleteShader(result); } } } else { // Failed shader alloc OutputDebugStringA("Failed shader alloc\n"); } } else { // Failed to open shader text file OutputDebugStringA("Failed to open shader file\n"); } return result; }
void initGL() { /* Initialize GLEW; this gives us access to OpenGL Extensions. */ glewInit(); /* Print information about OpenGL and ensure that we've got at a context * that supports least OpenGL 3.0. Then setup the OpenGL Debug message * mechanism. */ startupGLDiagnostics(); setupGLDebugMessages(); /* Workaround for AMD. It might no longer be necessary, but I dunno if we * are ever going to remove it. (Consider it a piece of living history.) */ if( !glBindFragDataLocation ) { glBindFragDataLocation = glBindFragDataLocationEXT; } /* As a general rule, you shouldn't need to change anything before this * comment in initGL(). */ // Define the positions for each of the three vertices of the triangle const float positions[] = { // X Y Z 0.0f, 0.5f, 1.0f, // v0 -0.5f, -0.5f, 1.0f, // v1 0.5f, -0.5f, 1.0f // v2 }; // Define the colors for each of the three vertices of the triangle const float colors[] = { // R G B 1.0f, 1.0f, 1.0f, // White 1.0f, 1.0f, 1.0f, // White 1.0f, 1.0f, 1.0f // White }; // Create a handle for the position vertex buffer object // See OpenGL Spec §2.9 Buffer Objects // - http://www.cse.chalmers.se/edu/course/TDA361/glspec30.20080923.pdf#page=54 GLuint positionBuffer; glGenBuffers( 1, &positionBuffer ); // Set the newly created buffer as the current one glBindBuffer( GL_ARRAY_BUFFER, positionBuffer ); // Send the vertex position data to the current buffer glBufferData( GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW ); // Create a handle for the vertex color buffer GLuint colorBuffer; glGenBuffers( 1, &colorBuffer ); // Set the newly created buffer as the current one glBindBuffer( GL_ARRAY_BUFFER, colorBuffer ); // Send the vertex color data to the current buffer glBufferData( GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW ); //******* Connect triangle data with the vertex array object ******* // // Connect the vertex buffer objects to the vertex array object // See OpenGL Spec §2.10 // - http://www.cse.chalmers.se/edu/course/TDA361/glspec30.20080923.pdf#page=64 glGenVertexArrays(1, &vertexArrayObject); // Bind the vertex array object // The following calls will affect this vertex array object. glBindVertexArray(vertexArrayObject); // Makes positionBuffer the current array buffer for subsequent calls. glBindBuffer( GL_ARRAY_BUFFER, positionBuffer ); // Attaches positionBuffer to vertexArrayObject, in the 0th attribute location glVertexAttribPointer(0, 3, GL_FLOAT, false/*normalized*/, 0/*stride*/, 0/*offset*/ ); // Makes colorBuffer the current array buffer for subsequent calls. glBindBuffer( GL_ARRAY_BUFFER, colorBuffer ); // Attaches colorBuffer to vertexArrayObject, in the 1st attribute location glVertexAttribPointer(1, 3, GL_FLOAT, false/*normalized*/, 0/*stride*/, 0/*offset*/ ); glEnableVertexAttribArray(0); // Enable the vertex position attribute glEnableVertexAttribArray(1); // Enable the vertex color attribute /////////////////////////////////////////////////////////////////////////// // Create shaders /////////////////////////////////////////////////////////////////////////// // See OpenGL spec §2.20 http://www.cse.chalmers.se/edu/course/TDA361/glspec30.20080923.pdf#page=104&zoom=75 GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); // Invoke helper functions (in glutil.h/cpp) to load text files for vertex and fragment shaders. const char *vs = textFileRead("simple.vert"); const char *fs = textFileRead("simple.frag"); glShaderSource(vertexShader, 1, &vs, NULL); glShaderSource(fragmentShader, 1, &fs, NULL); // we are now done with the source and can free the file data, textFileRead uses new [] to. // allocate the memory so we must free it using delete []. delete [] vs; delete [] fs; // Compile the shader, translates into internal representation and checks for errors. glCompileShader(vertexShader); int compileOK; // check for compiler errors in vertex shader. glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &compileOK); if(!compileOK) { std::string err = GetShaderInfoLog(vertexShader); fatal_error( err ); return; } // Compile the shader, translates into internal representation and checks for errors. glCompileShader(fragmentShader); // check for compiler errors in fragment shader. glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compileOK); if(!compileOK) { std::string err = GetShaderInfoLog(fragmentShader); fatal_error( err ); return; } // Create a program object and attach the two shaders we have compiled, the program object contains // both vertex and fragment shaders as well as information about uniforms and attributes common to both. shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, fragmentShader); glAttachShader(shaderProgram, vertexShader); // Now that the fragment and vertex shader has been attached, we no longer need these two separate objects and should delete them. // The attachment to the shader program will keep them alive, as long as we keep the shaderProgram. glDeleteShader( vertexShader ); glDeleteShader( fragmentShader ); // We have previously (in the glVertexAttribPointer calls) decided that our // vertex position data will be the 0th attribute. Bind the attribute with // name "position" to the 0th stream glBindAttribLocation(shaderProgram, 0, "position"); // And bind the attribute called "color" in the shader to the 1st attribute // stream. glBindAttribLocation(shaderProgram, 1, "color"); // This tells OpenGL which draw buffer the fragment shader out variable 'fragmentColor' will end up in. // Since we only use one output and draw buffer this is actually redundant, as the default will be correct. glBindFragDataLocation(shaderProgram, 0, "fragmentColor"); // Link the different shaders that are bound to this program, this creates a final shader that // we can use to render geometry with. glLinkProgram(shaderProgram); // Check for linker errors, many errors, such as mismatched in and out variables between // vertex/fragment shaders, do not appear before linking. { GLint linkOk = 0; glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linkOk); if(!linkOk) { std::string err = GetShaderInfoLog(shaderProgram); fatal_error( err ); return; } } }