util: check for frag/vertShader=0 before attaching
[mesa.git] / progs / util / shaderutil.c
1 /**
2 * Utilities for OpenGL shading language
3 *
4 * Brian Paul
5 * 9 April 2008
6 */
7
8
9 #include <assert.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <GL/glut.h>
13 #include "extfuncs.h"
14 #include "shaderutil.h"
15
16
17 static void
18 Init(void)
19 {
20 static GLboolean firstCall = GL_TRUE;
21 if (firstCall) {
22 GetExtensionFuncs();
23 firstCall = GL_FALSE;
24 }
25 }
26
27
28 GLboolean
29 ShadersSupported(void)
30 {
31 const char *version = (const char *) glGetString(GL_VERSION);
32 if (version[0] == '2' && version[1] == '.') {
33 return GL_TRUE;
34 }
35 else if (glutExtensionSupported("GL_ARB_vertex_shader")
36 && glutExtensionSupported("GL_ARB_fragment_shader")
37 && glutExtensionSupported("GL_ARB_shader_objects")) {
38 fprintf(stderr, "Warning: Trying ARB GLSL instead of OpenGL 2.x. This may not work.\n");
39 return GL_TRUE;
40 }
41 return GL_TRUE;
42 }
43
44
45 GLuint
46 CompileShaderText(GLenum shaderType, const char *text)
47 {
48 GLuint shader;
49 GLint stat;
50
51 Init();
52
53 shader = glCreateShader_func(shaderType);
54 glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
55 glCompileShader_func(shader);
56 glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
57 if (!stat) {
58 GLchar log[1000];
59 GLsizei len;
60 glGetShaderInfoLog_func(shader, 1000, &len, log);
61 fprintf(stderr, "Error: problem compiling shader: %s\n", log);
62 exit(1);
63 }
64 else {
65 /*printf("Shader compiled OK\n");*/
66 }
67 return shader;
68 }
69
70
71 /**
72 * Read a shader from a file.
73 */
74 GLuint
75 CompileShaderFile(GLenum shaderType, const char *filename)
76 {
77 const int max = 100*1000;
78 int n;
79 char *buffer = (char*) malloc(max);
80 GLuint shader;
81
82 FILE *f = fopen(filename, "r");
83 if (!f) {
84 fprintf(stderr, "Unable to open shader file %s\n", filename);
85 return 0;
86 }
87
88 n = fread(buffer, 1, max, f);
89 /*printf("read %d bytes from shader file %s\n", n, filename);*/
90 if (n > 0) {
91 buffer[n] = 0;
92 shader = CompileShaderText(shaderType, buffer);
93 }
94 else {
95 return 0;
96 }
97
98 fclose(f);
99 free(buffer);
100
101 return shader;
102 }
103
104
105 GLuint
106 LinkShaders(GLuint vertShader, GLuint fragShader)
107 {
108 GLuint program = glCreateProgram_func();
109
110 assert(vertShader || fragShader);
111
112 if (fragShader)
113 glAttachShader_func(program, fragShader);
114 if (vertShader)
115 glAttachShader_func(program, vertShader);
116 glLinkProgram_func(program);
117
118 /* check link */
119 {
120 GLint stat;
121 glGetProgramiv_func(program, GL_LINK_STATUS, &stat);
122 if (!stat) {
123 GLchar log[1000];
124 GLsizei len;
125 glGetProgramInfoLog_func(program, 1000, &len, log);
126 fprintf(stderr, "Shader link error:\n%s\n", log);
127 return 0;
128 }
129 }
130
131 return program;
132 }
133
134
135 void
136 InitUniforms(GLuint program, struct uniform_info uniforms[])
137 {
138 GLuint i;
139
140 for (i = 0; uniforms[i].name; i++) {
141 uniforms[i].location
142 = glGetUniformLocation_func(program, uniforms[i].name);
143
144 printf("Uniform %s location: %d\n", uniforms[i].name,
145 uniforms[i].location);
146
147 switch (uniforms[i].size) {
148 case 1:
149 if (uniforms[i].type == GL_INT)
150 glUniform1i_func(uniforms[i].location,
151 (GLint) uniforms[i].value[0]);
152 else
153 glUniform1fv_func(uniforms[i].location, 1, uniforms[i].value);
154 break;
155 case 2:
156 glUniform2fv_func(uniforms[i].location, 1, uniforms[i].value);
157 break;
158 case 3:
159 glUniform3fv_func(uniforms[i].location, 1, uniforms[i].value);
160 break;
161 case 4:
162 glUniform4fv_func(uniforms[i].location, 1, uniforms[i].value);
163 break;
164 default:
165 abort();
166 }
167 }
168 }