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 ¶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