sotest.c revision 32001f49
1/*
2 * GL_ARB_shader_objects & GL_ARB_vertex_shader interface test application.
3 * Neither compiler nor executor is being tested here, although some simple shader
4 * compilation tests are performed.
5 *
6 * Perfectly valid behaviour produces output that does not have a line
7 * beginning with three stars (***).
8 *
9 * Author: Michal Krol
10 */
11
12#include "framework.h"
13
14enum TEST_TYPE
15{
16   TT_GETERROR_NOERROR,
17   TT_GETERROR_INVALIDVALUE,
18   TT_GETERROR_INVALIDOPERATION,
19   TT_PARAM1_ZERO,
20   TT_PARAM1_NONZERO
21};
22
23static enum TEST_TYPE current_test;
24
25static void begintest (enum TEST_TYPE type, const char *name)
26{
27   current_test = type;
28   printf ("\n    BEGIN TEST: %s\n", name);
29   while (glGetError () != GL_NO_ERROR)
30      ;
31}
32
33static void endtest1 (GLuint param1)
34{
35   const char *msg = NULL;
36
37   switch (current_test)
38   {
39   case TT_GETERROR_NOERROR:
40      if (glGetError () != GL_NO_ERROR)
41         msg = "glGetError () does not return GL_NO_ERROR";
42      break;
43   case TT_GETERROR_INVALIDVALUE:
44      if (glGetError () != GL_INVALID_VALUE)
45         msg = "glGetError () does not return GL_INVALID_VALUE";
46      break;
47    case TT_GETERROR_INVALIDOPERATION:
48      if (glGetError () != GL_INVALID_OPERATION)
49         msg = "glGetError () does not return GL_INVALID_OPERATION";
50      break;
51   case TT_PARAM1_ZERO:
52      if (param1)
53         msg = "The parameter is not zero";
54      break;
55   case TT_PARAM1_NONZERO:
56      if (!param1)
57         msg = "The parameter is not non-zero";
58      break;
59   default:
60      assert (0);
61   }
62
63   if (msg == NULL)
64      printf ("    OK\n");
65   else
66      printf ("*** %s\n", msg);
67
68   while (glGetError () != GL_NO_ERROR)
69      ;
70}
71
72static void endtest (void)
73{
74   endtest1 (0);
75}
76
77static GLhandleARB vert = 0;
78static GLhandleARB frag = 0;
79static GLhandleARB prog = 0;
80
81static GLhandleARB find_invalid_handle (void)
82{
83   GLhandleARB handle;
84
85   for (handle = 1; handle < 16; handle++)
86      if (handle != vert && handle != frag && handle != prog)
87         return handle;
88   assert (0);
89   return 0;
90}
91
92static const char *invsynvertsrc =
93   "void main () {\n"
94   "   gl_Position = gl_ModelViewMatrix ! gl_Vertex;\n"   /* unexpected token */
95   "}\n"
96;
97
98static const char *invsemvertsrc =
99   "void main () {\n"
100   "   gl_Position = gl_ModelviewMatrix * gl_Vertex;\n"  /* undeclared identifier */
101   "}\n"
102;
103
104static const char *uniforms =
105   "uniform vec4 CommonUniform;\n"
106;
107
108static const char *validvertsrc =
109   "uniform vec4 VertexUniform;\n"
110   "attribute vec4 FirstAttrib;\n"
111   "attribute vec4 SecondAttrib;\n"
112   "void main () {\n"
113   "   gl_Position = gl_ModelViewMatrix * gl_Vertex + CommonUniform + VertexUniform\n"
114   "      + FirstAttrib + SecondAttrib;\n"
115   "}\n"
116;
117
118static const char *invsynfragsrc =
119   "void main () {\n"
120   "   gl_FragColor = gl_Color\n"   /* missing ; */
121   "}\n"
122;
123
124static const char *invsemfragsrc =
125   "void main () {\n"
126   "   gl_FragColor = gl_FrontColor;\n"   /* gl_FrontColor only in vertex shader */
127   "}\n"
128;
129
130static const char *validfragsrc =
131   "uniform vec4 FragmentUniform;\n"
132   "void main () {\n"
133   "   gl_FragColor = gl_Color + CommonUniform + FragmentUniform;\n"
134   "}\n"
135;
136
137void InitScene (void)
138{
139   GLint params[1];
140   const char *tab[2];
141
142   /*
143    * GL should silently ignore calls that delete object 0.
144    */
145   begintest (TT_GETERROR_NOERROR, "glDeleteObject(0)");
146   glDeleteObjectARB (0);
147   endtest ();
148
149   /*
150    * GL generates an error on invalid object handle.
151    */
152   begintest (TT_GETERROR_INVALIDVALUE, "Pass invalid non-zero object handle");
153   glDeleteObjectARB (find_invalid_handle ());
154   endtest ();
155   glUseProgramObjectARB (find_invalid_handle ());
156   endtest ();
157
158   /*
159    * Create object. GL should return unique non-zero values.
160    */
161   begintest (TT_PARAM1_NONZERO, "Create object");
162   vert = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
163   endtest1 (vert);
164   frag = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);
165   endtest1 (frag);
166   prog = glCreateProgramObjectARB ();
167   endtest1 (prog);
168   endtest1 (vert != frag && frag != prog && prog != vert);
169
170   /*
171    * Link empty program.
172    */
173   begintest (TT_PARAM1_NONZERO, "Link empty program");
174   glLinkProgramARB (prog);
175   endtest1 (CheckObjectStatus (prog));
176
177   /*
178    * Use empty program object. Empty program objects are valid.
179    */
180   begintest (TT_GETERROR_NOERROR, "Use empty program object");
181   glUseProgramObjectARB (prog);
182   endtest ();
183
184   /*
185    * Attach invalid object handles. Program object 0 should not be accepted.
186    */
187   begintest (TT_GETERROR_INVALIDVALUE, "Attach invalid object handle");
188   glAttachObjectARB (0, find_invalid_handle ());
189   endtest ();
190   glAttachObjectARB (0, frag);
191   endtest ();
192   glAttachObjectARB (find_invalid_handle (), find_invalid_handle ());
193   endtest ();
194   glAttachObjectARB (find_invalid_handle (), frag);
195   endtest ();
196   glAttachObjectARB (prog, find_invalid_handle ());
197   endtest ();
198
199   /*
200    * Attach valid object handles with wrong semantics.
201    */
202   begintest (TT_GETERROR_INVALIDOPERATION, "Attach object badly");
203   glAttachObjectARB (vert, frag);
204   endtest ();
205   glAttachObjectARB (vert, prog);
206   endtest ();
207   glAttachObjectARB (prog, prog);
208   endtest ();
209
210   /*
211    * Detach non-attached object.
212    */
213   begintest (TT_GETERROR_INVALIDOPERATION, "Detach non-attached object");
214   glDetachObjectARB (prog, vert);
215   endtest ();
216   glDetachObjectARB (prog, frag);
217   endtest ();
218
219   /*
220    * Attach shader.
221    */
222   begintest (TT_GETERROR_NOERROR, "Attach shader to program object");
223   glAttachObjectARB (prog, vert);
224   endtest ();
225   glAttachObjectARB (prog, frag);
226   endtest ();
227
228   /*
229    * Attach object twice.
230    */
231   begintest (TT_GETERROR_INVALIDOPERATION, "Attach object twice");
232   glAttachObjectARB (prog, vert);
233   endtest ();
234   glAttachObjectARB (prog, frag);
235   endtest ();
236
237   /*
238    * Detach attached object.
239    */
240   begintest (TT_GETERROR_NOERROR, "Detach attached object");
241   glDetachObjectARB (prog, vert);
242   endtest ();
243   glDetachObjectARB (prog, frag);
244   endtest ();
245
246   /*
247    * Attach shader again.
248    */
249   begintest (TT_GETERROR_NOERROR, "Attach shader again");
250   glAttachObjectARB (prog, vert);
251   endtest ();
252   glAttachObjectARB (prog, frag);
253   endtest ();
254
255   /*
256    * Delete attached object.
257    */
258   begintest (TT_GETERROR_NOERROR, "Delete attached object");
259   glDeleteObjectARB (vert);
260   endtest ();
261   glDeleteObjectARB (frag);
262   endtest ();
263
264   /*
265    * Query delete status. It should return TRUE. Object handles are still valid
266    * as they are referenced by program object container.
267    */
268   begintest (TT_PARAM1_NONZERO, "Query delete status");
269   glGetObjectParameterivARB (vert, GL_OBJECT_DELETE_STATUS_ARB, params);
270   endtest1 (params[0]);
271   glGetObjectParameterivARB (frag, GL_OBJECT_DELETE_STATUS_ARB, params);
272   endtest1 (params[0]);
273
274   /*
275    * Delete already deleted attached object. The behaviour is undefined, but we
276    * check for no errors. The object still exists, so the handle value is okay.
277    * In other words, these calls should be silently ignored by GL.
278    */
279   begintest (TT_GETERROR_NOERROR, "Delete already deleted attached object");
280   glDeleteObjectARB (vert);
281   endtest ();
282   glDeleteObjectARB (frag);
283   endtest ();
284
285   /*
286    * Compile shader source with syntax error.
287    */
288   begintest (TT_PARAM1_ZERO, "Compile shader source with syntax error");
289   glShaderSourceARB (vert, 1, &invsynvertsrc, NULL);
290   glCompileShaderARB (vert);
291   endtest1 (CheckObjectStatus (vert));
292   glShaderSourceARB (frag, 1, &invsynfragsrc, NULL);
293   glCompileShaderARB (frag);
294   endtest1 (CheckObjectStatus (frag));
295
296   /*
297    * Compile shader source with semantic error.
298    */
299   begintest (TT_PARAM1_ZERO, "Compile shader source with semantic error");
300   glShaderSourceARB (vert, 1, &invsemvertsrc, NULL);
301   glCompileShaderARB (vert);
302   endtest1 (CheckObjectStatus (vert));
303   glShaderSourceARB (frag, 1, &invsemfragsrc, NULL);
304   glCompileShaderARB (frag);
305   endtest1 (CheckObjectStatus (frag));
306
307   /*
308    * Link ill-formed vertex-fragment program.
309    */
310   begintest (TT_PARAM1_ZERO, "Link ill-formed vertex-fragment program");
311   glLinkProgramARB (prog);
312   endtest1 (CheckObjectStatus (prog));
313
314   /*
315    * Use badly linked program object.
316    */
317   begintest (TT_GETERROR_INVALIDOPERATION, "Use badly linked program object");
318   glUseProgramObjectARB (prog);
319   endtest ();
320
321   /*
322    * Compile well-formed shader source. Check if multi-string sources can be handled.
323    */
324   begintest (TT_PARAM1_NONZERO, "Compile well-formed shader source");
325   tab[0] = uniforms;
326   tab[1] = validvertsrc;
327   glShaderSourceARB (vert, 2, tab, NULL);
328   glCompileShaderARB (vert);
329   endtest1 (CheckObjectStatus (vert));
330   tab[0] = uniforms;
331   tab[1] = validfragsrc;
332   glShaderSourceARB (frag, 2, tab, NULL);
333   glCompileShaderARB (frag);
334   endtest1 (CheckObjectStatus (frag));
335
336   /*
337    * Link vertex-fragment program.
338    */
339   begintest (TT_PARAM1_NONZERO, "Link vertex-fragment program");
340   glLinkProgramARB (prog);
341   endtest1 (CheckObjectStatus (prog));
342
343   /*
344    * Use valid linked program object.
345    */
346   begintest (TT_GETERROR_NOERROR, "Use linked program object");
347   glUseProgramObjectARB (prog);
348   endtest ();
349
350   /*
351    * Get current program.
352    */
353   begintest (TT_PARAM1_NONZERO, "Get current program");
354   endtest1 (glGetHandleARB (GL_PROGRAM_OBJECT_ARB) == prog);
355
356   /*
357    * Use 0 program object.
358    */
359   begintest (TT_GETERROR_NOERROR, "Use 0 program object");
360   glUseProgramObjectARB (0);
361   endtest ();
362
363   /*
364    * Query uniform location. Uniforms with gl_ prefix cannot be queried.
365    */
366   begintest (TT_PARAM1_NONZERO, "Query uniform location");
367   endtest1 (glGetUniformLocationARB (prog, "gl_ModelViewMatrix") == -1);
368   endtest1 (glGetUniformLocationARB (prog, "UniformThatDoesNotExist") == -1);
369   endtest1 (glGetUniformLocationARB (prog, "") == -1);
370   endtest1 (glGetUniformLocationARB (prog, "CommonUniform") != -1);
371   endtest1 (glGetUniformLocationARB (prog, "VertexUniform") != -1);
372   endtest1 (glGetUniformLocationARB (prog, "FragmentUniform") != -1);
373
374   /*
375    * Query attrib location. Attribs with gl_ prefix cannot be queried.
376    * When gl_Vertex is used, none of the generic attribs can have index 0.
377    */
378   begintest (TT_PARAM1_NONZERO, "Query attrib location");
379   endtest1 (glGetAttribLocationARB (prog, "gl_Vertex") == -1);
380   endtest1 (glGetAttribLocationARB (prog, "AttribThatDoesNotExist") == -1);
381   endtest1 (glGetAttribLocationARB (prog, "") == -1);
382   endtest1 (glGetAttribLocationARB (prog, "FirstAttrib") > 0);
383   endtest1 (glGetAttribLocationARB (prog, "SecondAttrib") > 0);
384
385   /*
386    * Bind attrib locations, link and check if locations are correct.
387    */
388   begintest (TT_PARAM1_NONZERO, "Bind attrib location #1");
389   glBindAttribLocationARB (prog, 1, "FirstAttrib");
390   glBindAttribLocationARB (prog, 2, "SecondAttrib");
391   glLinkProgramARB (prog);
392   endtest1 (CheckObjectStatus (prog));
393   endtest1 (glGetAttribLocationARB (prog, "FirstAttrib") == 1);
394   endtest1 (glGetAttribLocationARB (prog, "SecondAttrib") == 2);
395
396   /*
397    * Bind attrib locations in different order. Link and check if locations are correct.
398    */
399   begintest (TT_PARAM1_NONZERO, "Bind attrib location #2");
400   glBindAttribLocationARB (prog, 1, "SecondAttrib");
401   glBindAttribLocationARB (prog, 2, "FirstAttrib");
402   glLinkProgramARB (prog);
403   endtest1 (CheckObjectStatus (prog));
404   endtest1 (glGetAttribLocationARB (prog, "SecondAttrib") == 1);
405   endtest1 (glGetAttribLocationARB (prog, "FirstAttrib") == 2);
406
407   /*
408    * Detach deleted object.
409    */
410   begintest (TT_GETERROR_NOERROR, "Detach deleted object");
411   glDetachObjectARB (prog, vert);
412   endtest ();
413   glDetachObjectARB (prog, frag);
414   endtest ();
415
416   /*
417    * Delete deleted detached object.
418    */
419   begintest (TT_GETERROR_INVALIDVALUE, "Delete deleted detached object");
420   glDeleteObjectARB (vert);
421   endtest ();
422   glDeleteObjectARB (frag);
423   endtest ();
424
425   exit (0);
426}
427
428void RenderScene (void)
429{
430   /* never reached */
431   assert (0);
432}
433
434int main (int argc, char *argv[])
435{
436   InitFramework (&argc, argv);
437   return 0;
438}
439
440