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