1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "shader.h" 17 18 #include <stdio.h> 19 #include <memory> 20 21 22 // Given shader source, load and compile it 23 static GLuint loadShader(GLenum type, const char *shaderSrc, const char *name) { 24 // Create the shader object 25 GLuint shader = glCreateShader (type); 26 if (shader == 0) { 27 return 0; 28 } 29 30 // Load and compile the shader 31 glShaderSource(shader, 1, &shaderSrc, nullptr); 32 glCompileShader(shader); 33 34 // Verify the compilation worked as expected 35 GLint compiled = 0; 36 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 37 if (!compiled) { 38 printf("Error compiling %s shader for %s\n", (type==GL_VERTEX_SHADER) ? "vtx":"pxl", name); 39 40 GLint size = 0; 41 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); 42 if (size > 0) 43 { 44 // Get and report the error message 45 std::unique_ptr<char> infoLog(new char[size]); 46 glGetShaderInfoLog(shader, size, NULL, infoLog.get()); 47 printf(" msg:\n%s\n", infoLog.get()); 48 } 49 50 glDeleteShader(shader); 51 return 0; 52 } 53 54 return shader; 55 } 56 57 58 // Create a program object given vertex and pixels shader source 59 GLuint buildShaderProgram(const char* vtxSrc, const char* pxlSrc, const char* name) { 60 GLuint program = glCreateProgram(); 61 if (program == 0) { 62 printf("Failed to allocate program object\n"); 63 return 0; 64 } 65 66 // Compile the shaders and bind them to this program 67 GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vtxSrc, name); 68 if (vertexShader == 0) { 69 printf("Failed to load vertex shader\n"); 70 glDeleteProgram(program); 71 return 0; 72 } 73 GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pxlSrc, name); 74 if (pixelShader == 0) { 75 printf("Failed to load pixel shader\n"); 76 glDeleteProgram(program); 77 glDeleteShader(vertexShader); 78 return 0; 79 } 80 glAttachShader(program, vertexShader); 81 glAttachShader(program, pixelShader); 82 83 // Link the program 84 glLinkProgram(program); 85 GLint linked = 0; 86 glGetProgramiv(program, GL_LINK_STATUS, &linked); 87 if (!linked) 88 { 89 printf("Error linking program.\n"); 90 GLint size = 0; 91 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &size); 92 if (size > 0) 93 { 94 // Get and report the error message 95 std::unique_ptr<char> infoLog(new char[size]); 96 glGetProgramInfoLog(program, size, NULL, infoLog.get()); 97 printf(" msg: %s\n", infoLog.get()); 98 } 99 100 glDeleteProgram(program); 101 glDeleteShader(vertexShader); 102 glDeleteShader(pixelShader); 103 return 0; 104 } 105 106 107 #if 0 // Debug output to diagnose shader parameters 108 GLint numShaderParams; 109 GLchar paramName[128]; 110 GLint paramSize; 111 GLenum paramType; 112 const char *typeName = "?"; 113 printf("Shader parameters for %s:\n", name); 114 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numShaderParams); 115 for (GLint i=0; i<numShaderParams; i++) { 116 glGetActiveUniform(program, 117 i, 118 sizeof(paramName), 119 nullptr, 120 ¶mSize, 121 ¶mType, 122 paramName); 123 switch (paramType) { 124 case GL_FLOAT: typeName = "GL_FLOAT"; break; 125 case GL_FLOAT_VEC4: typeName = "GL_FLOAT_VEC4"; break; 126 case GL_FLOAT_MAT4: typeName = "GL_FLOAT_MAT4"; break; 127 case GL_SAMPLER_2D: typeName = "GL_SAMPLER_2D"; break; 128 } 129 130 printf(" %2d: %s\t (%d) of type %s(%d)\n", i, paramName, paramSize, typeName, paramType); 131 } 132 #endif 133 134 135 return program; 136 } 137