st/xorg: Include cursorstr.h
[mesa.git] / progs / slang / cltest.c
1 /*
2 * GL_ARB_shading_language_100 test application.
3 *
4 * Tests correctness of emited code. Runs multiple well-formed shaders and checks if
5 * they produce valid results.
6 *
7 * Requires specific support on the GL implementation side. A special function printMESA()
8 * must be supported in the language that prints current values of generic type
9 * to the appropriate shader's info log, and optionally to the screen.
10 *
11 * Author: Michal Krol
12 */
13
14 #include "framework.h"
15
16 #define EPSILON 0.0001f
17
18 static GLhandleARB vert = 0;
19 static GLhandleARB prog = 0;
20
21 static int get_line (FILE *f, char *line, int size)
22 {
23 if (fgets (line, size, f) == NULL)
24 return 0;
25 if (line[strlen (line) - 1] == '\n')
26 line[strlen (line) - 1] = '\0';
27 return 1;
28 }
29
30 struct ATTRIB
31 {
32 char name[32];
33 GLfloat value[64][4];
34 GLuint count;
35 };
36
37 struct ATTRIBS
38 {
39 struct ATTRIB attrib[32];
40 GLuint count;
41 };
42
43 struct SHADER
44 {
45 char code[16000];
46 GLfloat output[1000];
47 GLuint count;
48 };
49
50 enum SHADER_LOAD_STATE
51 {
52 SLS_NONE,
53 SLS_CODE,
54 SLS_OUTPUT
55 };
56
57 struct PROGRAM
58 {
59 struct PROGRAM *next;
60 char name[256];
61 struct ATTRIBS attribs;
62 struct SHADER vertex;
63 };
64
65 enum PROGRAM_LOAD_STATE
66 {
67 PLS_NONE,
68 PLS_ATTRIB,
69 PLS_VERTEX
70 };
71
72 static struct PROGRAM *program = NULL;
73
74 static void load_test_file (const char *filename, struct PROGRAM **program)
75 {
76 struct PROGRAM **currprog = program;
77 FILE *f;
78 char line[256];
79 enum PROGRAM_LOAD_STATE pls = PLS_NONE;
80 enum SHADER_LOAD_STATE sls = SLS_NONE;
81
82 f = fopen (filename, "r");
83 if (f == NULL)
84 return;
85
86 while (get_line (f, line, sizeof (line))) {
87 if (line[0] == '$') {
88 if (strncmp (line + 1, "program", 7) == 0) {
89 if (*currprog != NULL)
90 currprog = &(**currprog).next;
91 *currprog = (struct PROGRAM *) (malloc (sizeof (struct PROGRAM)));
92 if (*currprog == NULL)
93 break;
94 (**currprog).next = NULL;
95 strcpy ((**currprog).name, line + 9);
96 (**currprog).attribs.count = 0;
97 (**currprog).vertex.code[0] = '\0';
98 (**currprog).vertex.count = 0;
99 pls = PLS_NONE;
100 }
101 else if (strncmp (line + 1, "attrib", 6) == 0) {
102 if (*currprog == NULL)
103 break;
104 strcpy ((**currprog).attribs.attrib[(**currprog).attribs.count].name, line + 8);
105 (**currprog).attribs.attrib[(**currprog).attribs.count].count = 0;
106 (**currprog).attribs.count++;
107 pls = PLS_ATTRIB;
108 }
109 else if (strcmp (line + 1, "vertex") == 0) {
110 if (*currprog == NULL)
111 break;
112 pls = PLS_VERTEX;
113 sls = SLS_NONE;
114 }
115 else if (strcmp (line + 1, "code") == 0) {
116 if (*currprog == NULL || pls != PLS_VERTEX)
117 break;
118 sls = SLS_CODE;
119 }
120 else if (strcmp (line + 1, "output") == 0) {
121 if (*currprog == NULL || pls != PLS_VERTEX)
122 break;
123 sls = SLS_OUTPUT;
124 }
125 }
126 else {
127 if ((*currprog == NULL || pls == PLS_NONE || sls == SLS_NONE) && line[0] != '\0')
128 break;
129 if (*currprog != NULL && pls == PLS_VERTEX) {
130 if (sls == SLS_CODE) {
131 strcat ((**currprog).vertex.code, line);
132 strcat ((**currprog).vertex.code, "\n");
133 }
134 else if (sls == SLS_OUTPUT && line[0] != '\0') {
135 if (strcmp (line, "true") == 0)
136 (**currprog).vertex.output[(**currprog).vertex.count] = 1.0f;
137 else if (strcmp (line, "false") == 0)
138 (**currprog).vertex.output[(**currprog).vertex.count] = 0.0f;
139 else
140 sscanf (line, "%f", &(**currprog).vertex.output[(**currprog).vertex.count]);
141 (**currprog).vertex.count++;
142 }
143 }
144 else if (*currprog != NULL && pls == PLS_ATTRIB && line[0] != '\0') {
145 struct ATTRIB *att = &(**currprog).attribs.attrib[(**currprog).attribs.count - 1];
146 GLfloat *vec = att->value[att->count];
147 sscanf (line, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
148 att->count++;
149 }
150 }
151 }
152
153 fclose (f);
154 }
155
156 void InitScene (void)
157 {
158 prog = glCreateProgramObjectARB ();
159 vert = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
160 glAttachObjectARB (prog, vert);
161 glDeleteObjectARB (vert);
162 load_test_file ("cltest.txt", &program);
163 }
164
165 void RenderScene (void)
166 {
167 struct PROGRAM *nextprogram;
168 char *code;
169 GLint info_length, length;
170 char output[65000], *p;
171 GLuint i;
172
173 if (program == NULL)
174 exit (0);
175
176 code = program->vertex.code;
177 glShaderSourceARB (vert, 1, (const GLcharARB **) (&code), NULL);
178 glCompileShaderARB (vert);
179 CheckObjectStatus (vert);
180
181 for (i = 0; i < program->attribs.count; i++) {
182 const char *name = program->attribs.attrib[i].name;
183 if (strcmp (name, "gl_Vertex") != 0)
184 glBindAttribLocationARB (prog, i, name);
185 }
186
187 glLinkProgramARB (prog);
188 CheckObjectStatus (prog);
189 glUseProgramObjectARB (prog);
190
191 printf ("\n--- %s\n", program->name);
192
193 glGetObjectParameterivARB (vert, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_length);
194
195 glBegin (GL_POINTS);
196 if (program->attribs.count == 0) {
197 glVertex2f (0.0f, 0.0f);
198 }
199 else {
200 for (i = 0; i < program->attribs.attrib[0].count; i++) {
201 GLuint j;
202 for (j = 0; j < program->attribs.count; j++) {
203 GLuint n = (j + 1) % program->attribs.count;
204 GLfloat *vec = program->attribs.attrib[n].value[i];
205 const char *name = program->attribs.attrib[n].name;
206 if (strcmp (name, "gl_Vertex") == 0)
207 glVertex4fv (vec);
208 else
209 glVertexAttrib4fvARB (n, vec);
210 }
211 }
212 }
213 glEnd ();
214 glFlush ();
215
216 glGetInfoLogARB (vert, sizeof (output), &length, output);
217 p = output + info_length - 1;
218 for (i = 0; i < program->vertex.count; i++) {
219 GLfloat value;
220 if (p == NULL) {
221 printf ("*** %s\n", "I/O error");
222 break;
223 }
224 if (strncmp (p, "true", 4) == 0)
225 value = 1.0f;
226 else if (strncmp (p, "false", 5) == 0)
227 value = 0.0f;
228 else if (sscanf (p, "%f", &value) != 1) {
229 printf ("*** %s\n", "I/O error");
230 break;
231 }
232 if (fabs (value - program->vertex.output[i]) > EPSILON) {
233 printf ("*** Values are different, is %f, should be %f\n", value,
234 program->vertex.output[i]);
235 }
236 p = strchr (p, '\n');
237 if (p != NULL)
238 p++;
239 }
240 if (p && *p != '\0')
241 printf ("*** %s\n", "I/O error");
242
243 nextprogram = program->next;
244 free (program);
245 program = nextprogram;
246 }
247
248 int main (int argc, char *argv[])
249 {
250 InitFramework (&argc, argv);
251 return 0;
252 }
253