Merge commit 'origin/gallium-0.1' 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 return 0;
84 }
85
86 n = fread(buffer, 1, max, f);
87 /*printf("read %d bytes from shader file %s\n", n, filename);*/
88 if (n > 0) {
89 buffer[n] = 0;
90 shader = CompileShaderText(shaderType, buffer);
91 }
92 else {
93 return 0;
94 }
95
96 fclose(f);
97 free(buffer);
98
99 return shader;
100 }
101
102
103 GLuint
104 LinkShaders(GLuint vertShader, GLuint fragShader)
105 {
106 GLuint program = glCreateProgram_func();
107
108 glAttachShader_func(program, fragShader);
109 glAttachShader_func(program, vertShader);
110 glLinkProgram_func(program);
111
112 /* check link */
113 {
114 GLint stat;
115 glGetProgramiv_func(program, GL_LINK_STATUS, &stat);
116 if (!stat) {
117 GLchar log[1000];
118 GLsizei len;
119 glGetProgramInfoLog_func(program, 1000, &len, log);
120 fprintf(stderr, "Shader link error:\n%s\n", log);
121 return 0;
122 }
123 }
124
125 return program;
126 }
127
128
129 void
130 InitUniforms(GLuint program, struct uniform_info uniforms[])
131 {
132 GLuint i;
133
134 for (i = 0; uniforms[i].name; i++) {
135 uniforms[i].location
136 = glGetUniformLocation_func(program, uniforms[i].name);
137
138 printf("Uniform %s location: %d\n", uniforms[i].name,
139 uniforms[i].location);
140
141 switch (uniforms[i].size) {
142 case 1:
143 if (uniforms[i].type == GL_INT)
144 glUniform1i_func(uniforms[i].location,
145 (GLint) uniforms[i].value[0]);
146 else
147 glUniform1fv_func(uniforms[i].location, 1, uniforms[i].value);
148 break;
149 case 2:
150 glUniform2fv_func(uniforms[i].location, 1, uniforms[i].value);
151 break;
152 case 3:
153 glUniform3fv_func(uniforms[i].location, 1, uniforms[i].value);
154 break;
155 case 4:
156 glUniform4fv_func(uniforms[i].location, 1, uniforms[i].value);
157 break;
158 default:
159 abort();
160 }
161 }
162 }