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
loadShader(GLenum type,const char * shaderSrc,const char * name)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
buildShaderProgram(const char * vtxSrc,const char * pxlSrc,const char * name)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                            &paramSize,
121                            &paramType,
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