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
20 #include <memory>
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",
39 name);
40
41 GLint size = 0;
42 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
43 if (size > 0) {
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 // Create a program object given vertex and pixels shader source
buildShaderProgram(const char * vtxSrc,const char * pxlSrc,const char * name)58 GLuint buildShaderProgram(const char* vtxSrc, const char* pxlSrc, const char* name) {
59 GLuint program = glCreateProgram();
60 if (program == 0) {
61 printf("Failed to allocate program object\n");
62 return 0;
63 }
64
65 // Compile the shaders and bind them to this program
66 GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vtxSrc, name);
67 if (vertexShader == 0) {
68 printf("Failed to load vertex shader\n");
69 glDeleteProgram(program);
70 return 0;
71 }
72 GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pxlSrc, name);
73 if (pixelShader == 0) {
74 printf("Failed to load pixel shader\n");
75 glDeleteProgram(program);
76 glDeleteShader(vertexShader);
77 return 0;
78 }
79 glAttachShader(program, vertexShader);
80 glAttachShader(program, pixelShader);
81
82 // Link the program
83 glLinkProgram(program);
84 GLint linked = 0;
85 glGetProgramiv(program, GL_LINK_STATUS, &linked);
86 if (!linked) {
87 printf("Error linking program.\n");
88 GLint size = 0;
89 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &size);
90 if (size > 0) {
91 // Get and report the error message
92 std::unique_ptr<char> infoLog(new char[size]);
93 glGetProgramInfoLog(program, size, NULL, infoLog.get());
94 printf(" msg: %s\n", infoLog.get());
95 }
96
97 glDeleteProgram(program);
98 glDeleteShader(vertexShader);
99 glDeleteShader(pixelShader);
100 return 0;
101 }
102
103 #if defined(DEBUG) // Debug output to diagnose shader parameters
104 GLint numShaderParams;
105 GLchar paramName[128];
106 GLint paramSize;
107 GLenum paramType;
108 const char* typeName = "?";
109 printf("Shader parameters for %s:\n", name);
110 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numShaderParams);
111 for (GLint i = 0; i < numShaderParams; i++) {
112 glGetActiveUniform(program, i, sizeof(paramName), nullptr, ¶mSize, ¶mType,
113 paramName);
114 switch (paramType) {
115 case GL_FLOAT:
116 typeName = "GL_FLOAT";
117 break;
118 case GL_FLOAT_VEC4:
119 typeName = "GL_FLOAT_VEC4";
120 break;
121 case GL_FLOAT_MAT4:
122 typeName = "GL_FLOAT_MAT4";
123 break;
124 case GL_SAMPLER_2D:
125 typeName = "GL_SAMPLER_2D";
126 break;
127 }
128
129 printf(" %2d: %s\t (%d) of type %s(%d)\n", i, paramName, paramSize, typeName, paramType);
130 }
131 #endif
132
133 return program;
134 }
135