132001f49Smrg/*
232001f49Smrg * GL_ARB_shader_objects & GL_ARB_vertex_shader interface test application.
332001f49Smrg * Neither compiler nor executor is being tested here, although some simple shader
432001f49Smrg * compilation tests are performed.
532001f49Smrg *
632001f49Smrg * Perfectly valid behaviour produces output that does not have a line
732001f49Smrg * beginning with three stars (***).
832001f49Smrg *
932001f49Smrg * Author: Michal Krol
1032001f49Smrg */
1132001f49Smrg
1232001f49Smrg#include "framework.h"
1332001f49Smrg
1432001f49Smrgenum TEST_TYPE
1532001f49Smrg{
1632001f49Smrg   TT_GETERROR_NOERROR,
1732001f49Smrg   TT_GETERROR_INVALIDVALUE,
1832001f49Smrg   TT_GETERROR_INVALIDOPERATION,
1932001f49Smrg   TT_PARAM1_ZERO,
2032001f49Smrg   TT_PARAM1_NONZERO
2132001f49Smrg};
2232001f49Smrg
2332001f49Smrgstatic enum TEST_TYPE current_test;
2432001f49Smrg
2532001f49Smrgstatic void begintest (enum TEST_TYPE type, const char *name)
2632001f49Smrg{
2732001f49Smrg   current_test = type;
2832001f49Smrg   printf ("\n    BEGIN TEST: %s\n", name);
2932001f49Smrg   while (glGetError () != GL_NO_ERROR)
3032001f49Smrg      ;
3132001f49Smrg}
3232001f49Smrg
3332001f49Smrgstatic void endtest1 (GLuint param1)
3432001f49Smrg{
3532001f49Smrg   const char *msg = NULL;
3632001f49Smrg
3732001f49Smrg   switch (current_test)
3832001f49Smrg   {
3932001f49Smrg   case TT_GETERROR_NOERROR:
4032001f49Smrg      if (glGetError () != GL_NO_ERROR)
4132001f49Smrg         msg = "glGetError () does not return GL_NO_ERROR";
4232001f49Smrg      break;
4332001f49Smrg   case TT_GETERROR_INVALIDVALUE:
4432001f49Smrg      if (glGetError () != GL_INVALID_VALUE)
4532001f49Smrg         msg = "glGetError () does not return GL_INVALID_VALUE";
4632001f49Smrg      break;
4732001f49Smrg    case TT_GETERROR_INVALIDOPERATION:
4832001f49Smrg      if (glGetError () != GL_INVALID_OPERATION)
4932001f49Smrg         msg = "glGetError () does not return GL_INVALID_OPERATION";
5032001f49Smrg      break;
5132001f49Smrg   case TT_PARAM1_ZERO:
5232001f49Smrg      if (param1)
5332001f49Smrg         msg = "The parameter is not zero";
5432001f49Smrg      break;
5532001f49Smrg   case TT_PARAM1_NONZERO:
5632001f49Smrg      if (!param1)
5732001f49Smrg         msg = "The parameter is not non-zero";
5832001f49Smrg      break;
5932001f49Smrg   default:
6032001f49Smrg      assert (0);
6132001f49Smrg   }
6232001f49Smrg
6332001f49Smrg   if (msg == NULL)
6432001f49Smrg      printf ("    OK\n");
6532001f49Smrg   else
6632001f49Smrg      printf ("*** %s\n", msg);
6732001f49Smrg
6832001f49Smrg   while (glGetError () != GL_NO_ERROR)
6932001f49Smrg      ;
7032001f49Smrg}
7132001f49Smrg
7232001f49Smrgstatic void endtest (void)
7332001f49Smrg{
7432001f49Smrg   endtest1 (0);
7532001f49Smrg}
7632001f49Smrg
7732001f49Smrgstatic GLhandleARB vert = 0;
7832001f49Smrgstatic GLhandleARB frag = 0;
7932001f49Smrgstatic GLhandleARB prog = 0;
8032001f49Smrg
8132001f49Smrgstatic GLhandleARB find_invalid_handle (void)
8232001f49Smrg{
8332001f49Smrg   GLhandleARB handle;
8432001f49Smrg
8532001f49Smrg   for (handle = 1; handle < 16; handle++)
8632001f49Smrg      if (handle != vert && handle != frag && handle != prog)
8732001f49Smrg         return handle;
8832001f49Smrg   assert (0);
8932001f49Smrg   return 0;
9032001f49Smrg}
9132001f49Smrg
9232001f49Smrgstatic const char *invsynvertsrc =
9332001f49Smrg   "void main () {\n"
9432001f49Smrg   "   gl_Position = gl_ModelViewMatrix ! gl_Vertex;\n"   /* unexpected token */
9532001f49Smrg   "}\n"
9632001f49Smrg;
9732001f49Smrg
9832001f49Smrgstatic const char *invsemvertsrc =
9932001f49Smrg   "void main () {\n"
10032001f49Smrg   "   gl_Position = gl_ModelviewMatrix * gl_Vertex;\n"  /* undeclared identifier */
10132001f49Smrg   "}\n"
10232001f49Smrg;
10332001f49Smrg
10432001f49Smrgstatic const char *uniforms =
10532001f49Smrg   "uniform vec4 CommonUniform;\n"
10632001f49Smrg;
10732001f49Smrg
10832001f49Smrgstatic const char *validvertsrc =
10932001f49Smrg   "uniform vec4 VertexUniform;\n"
11032001f49Smrg   "attribute vec4 FirstAttrib;\n"
11132001f49Smrg   "attribute vec4 SecondAttrib;\n"
11232001f49Smrg   "void main () {\n"
11332001f49Smrg   "   gl_Position = gl_ModelViewMatrix * gl_Vertex + CommonUniform + VertexUniform\n"
11432001f49Smrg   "      + FirstAttrib + SecondAttrib;\n"
11532001f49Smrg   "}\n"
11632001f49Smrg;
11732001f49Smrg
11832001f49Smrgstatic const char *invsynfragsrc =
11932001f49Smrg   "void main () {\n"
12032001f49Smrg   "   gl_FragColor = gl_Color\n"   /* missing ; */
12132001f49Smrg   "}\n"
12232001f49Smrg;
12332001f49Smrg
12432001f49Smrgstatic const char *invsemfragsrc =
12532001f49Smrg   "void main () {\n"
12632001f49Smrg   "   gl_FragColor = gl_FrontColor;\n"   /* gl_FrontColor only in vertex shader */
12732001f49Smrg   "}\n"
12832001f49Smrg;
12932001f49Smrg
13032001f49Smrgstatic const char *validfragsrc =
13132001f49Smrg   "uniform vec4 FragmentUniform;\n"
13232001f49Smrg   "void main () {\n"
13332001f49Smrg   "   gl_FragColor = gl_Color + CommonUniform + FragmentUniform;\n"
13432001f49Smrg   "}\n"
13532001f49Smrg;
13632001f49Smrg
13732001f49Smrgvoid InitScene (void)
13832001f49Smrg{
13932001f49Smrg   GLint params[1];
14032001f49Smrg   const char *tab[2];
14132001f49Smrg
14232001f49Smrg   /*
14332001f49Smrg    * GL should silently ignore calls that delete object 0.
14432001f49Smrg    */
14532001f49Smrg   begintest (TT_GETERROR_NOERROR, "glDeleteObject(0)");
14632001f49Smrg   glDeleteObjectARB (0);
14732001f49Smrg   endtest ();
14832001f49Smrg
14932001f49Smrg   /*
15032001f49Smrg    * GL generates an error on invalid object handle.
15132001f49Smrg    */
15232001f49Smrg   begintest (TT_GETERROR_INVALIDVALUE, "Pass invalid non-zero object handle");
15332001f49Smrg   glDeleteObjectARB (find_invalid_handle ());
15432001f49Smrg   endtest ();
15532001f49Smrg   glUseProgramObjectARB (find_invalid_handle ());
15632001f49Smrg   endtest ();
15732001f49Smrg
15832001f49Smrg   /*
15932001f49Smrg    * Create object. GL should return unique non-zero values.
16032001f49Smrg    */
16132001f49Smrg   begintest (TT_PARAM1_NONZERO, "Create object");
16232001f49Smrg   vert = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
16332001f49Smrg   endtest1 (vert);
16432001f49Smrg   frag = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);
16532001f49Smrg   endtest1 (frag);
16632001f49Smrg   prog = glCreateProgramObjectARB ();
16732001f49Smrg   endtest1 (prog);
16832001f49Smrg   endtest1 (vert != frag && frag != prog && prog != vert);
16932001f49Smrg
17032001f49Smrg   /*
17132001f49Smrg    * Link empty program.
17232001f49Smrg    */
17332001f49Smrg   begintest (TT_PARAM1_NONZERO, "Link empty program");
17432001f49Smrg   glLinkProgramARB (prog);
17532001f49Smrg   endtest1 (CheckObjectStatus (prog));
17632001f49Smrg
17732001f49Smrg   /*
17832001f49Smrg    * Use empty program object. Empty program objects are valid.
17932001f49Smrg    */
18032001f49Smrg   begintest (TT_GETERROR_NOERROR, "Use empty program object");
18132001f49Smrg   glUseProgramObjectARB (prog);
18232001f49Smrg   endtest ();
18332001f49Smrg
18432001f49Smrg   /*
18532001f49Smrg    * Attach invalid object handles. Program object 0 should not be accepted.
18632001f49Smrg    */
18732001f49Smrg   begintest (TT_GETERROR_INVALIDVALUE, "Attach invalid object handle");
18832001f49Smrg   glAttachObjectARB (0, find_invalid_handle ());
18932001f49Smrg   endtest ();
19032001f49Smrg   glAttachObjectARB (0, frag);
19132001f49Smrg   endtest ();
19232001f49Smrg   glAttachObjectARB (find_invalid_handle (), find_invalid_handle ());
19332001f49Smrg   endtest ();
19432001f49Smrg   glAttachObjectARB (find_invalid_handle (), frag);
19532001f49Smrg   endtest ();
19632001f49Smrg   glAttachObjectARB (prog, find_invalid_handle ());
19732001f49Smrg   endtest ();
19832001f49Smrg
19932001f49Smrg   /*
20032001f49Smrg    * Attach valid object handles with wrong semantics.
20132001f49Smrg    */
20232001f49Smrg   begintest (TT_GETERROR_INVALIDOPERATION, "Attach object badly");
20332001f49Smrg   glAttachObjectARB (vert, frag);
20432001f49Smrg   endtest ();
20532001f49Smrg   glAttachObjectARB (vert, prog);
20632001f49Smrg   endtest ();
20732001f49Smrg   glAttachObjectARB (prog, prog);
20832001f49Smrg   endtest ();
20932001f49Smrg
21032001f49Smrg   /*
21132001f49Smrg    * Detach non-attached object.
21232001f49Smrg    */
21332001f49Smrg   begintest (TT_GETERROR_INVALIDOPERATION, "Detach non-attached object");
21432001f49Smrg   glDetachObjectARB (prog, vert);
21532001f49Smrg   endtest ();
21632001f49Smrg   glDetachObjectARB (prog, frag);
21732001f49Smrg   endtest ();
21832001f49Smrg
21932001f49Smrg   /*
22032001f49Smrg    * Attach shader.
22132001f49Smrg    */
22232001f49Smrg   begintest (TT_GETERROR_NOERROR, "Attach shader to program object");
22332001f49Smrg   glAttachObjectARB (prog, vert);
22432001f49Smrg   endtest ();
22532001f49Smrg   glAttachObjectARB (prog, frag);
22632001f49Smrg   endtest ();
22732001f49Smrg
22832001f49Smrg   /*
22932001f49Smrg    * Attach object twice.
23032001f49Smrg    */
23132001f49Smrg   begintest (TT_GETERROR_INVALIDOPERATION, "Attach object twice");
23232001f49Smrg   glAttachObjectARB (prog, vert);
23332001f49Smrg   endtest ();
23432001f49Smrg   glAttachObjectARB (prog, frag);
23532001f49Smrg   endtest ();
23632001f49Smrg
23732001f49Smrg   /*
23832001f49Smrg    * Detach attached object.
23932001f49Smrg    */
24032001f49Smrg   begintest (TT_GETERROR_NOERROR, "Detach attached object");
24132001f49Smrg   glDetachObjectARB (prog, vert);
24232001f49Smrg   endtest ();
24332001f49Smrg   glDetachObjectARB (prog, frag);
24432001f49Smrg   endtest ();
24532001f49Smrg
24632001f49Smrg   /*
24732001f49Smrg    * Attach shader again.
24832001f49Smrg    */
24932001f49Smrg   begintest (TT_GETERROR_NOERROR, "Attach shader again");
25032001f49Smrg   glAttachObjectARB (prog, vert);
25132001f49Smrg   endtest ();
25232001f49Smrg   glAttachObjectARB (prog, frag);
25332001f49Smrg   endtest ();
25432001f49Smrg
25532001f49Smrg   /*
25632001f49Smrg    * Delete attached object.
25732001f49Smrg    */
25832001f49Smrg   begintest (TT_GETERROR_NOERROR, "Delete attached object");
25932001f49Smrg   glDeleteObjectARB (vert);
26032001f49Smrg   endtest ();
26132001f49Smrg   glDeleteObjectARB (frag);
26232001f49Smrg   endtest ();
26332001f49Smrg
26432001f49Smrg   /*
26532001f49Smrg    * Query delete status. It should return TRUE. Object handles are still valid
26632001f49Smrg    * as they are referenced by program object container.
26732001f49Smrg    */
26832001f49Smrg   begintest (TT_PARAM1_NONZERO, "Query delete status");
26932001f49Smrg   glGetObjectParameterivARB (vert, GL_OBJECT_DELETE_STATUS_ARB, params);
27032001f49Smrg   endtest1 (params[0]);
27132001f49Smrg   glGetObjectParameterivARB (frag, GL_OBJECT_DELETE_STATUS_ARB, params);
27232001f49Smrg   endtest1 (params[0]);
27332001f49Smrg
27432001f49Smrg   /*
27532001f49Smrg    * Delete already deleted attached object. The behaviour is undefined, but we
27632001f49Smrg    * check for no errors. The object still exists, so the handle value is okay.
27732001f49Smrg    * In other words, these calls should be silently ignored by GL.
27832001f49Smrg    */
27932001f49Smrg   begintest (TT_GETERROR_NOERROR, "Delete already deleted attached object");
28032001f49Smrg   glDeleteObjectARB (vert);
28132001f49Smrg   endtest ();
28232001f49Smrg   glDeleteObjectARB (frag);
28332001f49Smrg   endtest ();
28432001f49Smrg
28532001f49Smrg   /*
28632001f49Smrg    * Compile shader source with syntax error.
28732001f49Smrg    */
28832001f49Smrg   begintest (TT_PARAM1_ZERO, "Compile shader source with syntax error");
28932001f49Smrg   glShaderSourceARB (vert, 1, &invsynvertsrc, NULL);
29032001f49Smrg   glCompileShaderARB (vert);
29132001f49Smrg   endtest1 (CheckObjectStatus (vert));
29232001f49Smrg   glShaderSourceARB (frag, 1, &invsynfragsrc, NULL);
29332001f49Smrg   glCompileShaderARB (frag);
29432001f49Smrg   endtest1 (CheckObjectStatus (frag));
29532001f49Smrg
29632001f49Smrg   /*
29732001f49Smrg    * Compile shader source with semantic error.
29832001f49Smrg    */
29932001f49Smrg   begintest (TT_PARAM1_ZERO, "Compile shader source with semantic error");
30032001f49Smrg   glShaderSourceARB (vert, 1, &invsemvertsrc, NULL);
30132001f49Smrg   glCompileShaderARB (vert);
30232001f49Smrg   endtest1 (CheckObjectStatus (vert));
30332001f49Smrg   glShaderSourceARB (frag, 1, &invsemfragsrc, NULL);
30432001f49Smrg   glCompileShaderARB (frag);
30532001f49Smrg   endtest1 (CheckObjectStatus (frag));
30632001f49Smrg
30732001f49Smrg   /*
30832001f49Smrg    * Link ill-formed vertex-fragment program.
30932001f49Smrg    */
31032001f49Smrg   begintest (TT_PARAM1_ZERO, "Link ill-formed vertex-fragment program");
31132001f49Smrg   glLinkProgramARB (prog);
31232001f49Smrg   endtest1 (CheckObjectStatus (prog));
31332001f49Smrg
31432001f49Smrg   /*
31532001f49Smrg    * Use badly linked program object.
31632001f49Smrg    */
31732001f49Smrg   begintest (TT_GETERROR_INVALIDOPERATION, "Use badly linked program object");
31832001f49Smrg   glUseProgramObjectARB (prog);
31932001f49Smrg   endtest ();
32032001f49Smrg
32132001f49Smrg   /*
32232001f49Smrg    * Compile well-formed shader source. Check if multi-string sources can be handled.
32332001f49Smrg    */
32432001f49Smrg   begintest (TT_PARAM1_NONZERO, "Compile well-formed shader source");
32532001f49Smrg   tab[0] = uniforms;
32632001f49Smrg   tab[1] = validvertsrc;
32732001f49Smrg   glShaderSourceARB (vert, 2, tab, NULL);
32832001f49Smrg   glCompileShaderARB (vert);
32932001f49Smrg   endtest1 (CheckObjectStatus (vert));
33032001f49Smrg   tab[0] = uniforms;
33132001f49Smrg   tab[1] = validfragsrc;
33232001f49Smrg   glShaderSourceARB (frag, 2, tab, NULL);
33332001f49Smrg   glCompileShaderARB (frag);
33432001f49Smrg   endtest1 (CheckObjectStatus (frag));
33532001f49Smrg
33632001f49Smrg   /*
33732001f49Smrg    * Link vertex-fragment program.
33832001f49Smrg    */
33932001f49Smrg   begintest (TT_PARAM1_NONZERO, "Link vertex-fragment program");
34032001f49Smrg   glLinkProgramARB (prog);
34132001f49Smrg   endtest1 (CheckObjectStatus (prog));
34232001f49Smrg
34332001f49Smrg   /*
34432001f49Smrg    * Use valid linked program object.
34532001f49Smrg    */
34632001f49Smrg   begintest (TT_GETERROR_NOERROR, "Use linked program object");
34732001f49Smrg   glUseProgramObjectARB (prog);
34832001f49Smrg   endtest ();
34932001f49Smrg
35032001f49Smrg   /*
35132001f49Smrg    * Get current program.
35232001f49Smrg    */
35332001f49Smrg   begintest (TT_PARAM1_NONZERO, "Get current program");
35432001f49Smrg   endtest1 (glGetHandleARB (GL_PROGRAM_OBJECT_ARB) == prog);
35532001f49Smrg
35632001f49Smrg   /*
35732001f49Smrg    * Use 0 program object.
35832001f49Smrg    */
35932001f49Smrg   begintest (TT_GETERROR_NOERROR, "Use 0 program object");
36032001f49Smrg   glUseProgramObjectARB (0);
36132001f49Smrg   endtest ();
36232001f49Smrg
36332001f49Smrg   /*
36432001f49Smrg    * Query uniform location. Uniforms with gl_ prefix cannot be queried.
36532001f49Smrg    */
36632001f49Smrg   begintest (TT_PARAM1_NONZERO, "Query uniform location");
36732001f49Smrg   endtest1 (glGetUniformLocationARB (prog, "gl_ModelViewMatrix") == -1);
36832001f49Smrg   endtest1 (glGetUniformLocationARB (prog, "UniformThatDoesNotExist") == -1);
36932001f49Smrg   endtest1 (glGetUniformLocationARB (prog, "") == -1);
37032001f49Smrg   endtest1 (glGetUniformLocationARB (prog, "CommonUniform") != -1);
37132001f49Smrg   endtest1 (glGetUniformLocationARB (prog, "VertexUniform") != -1);
37232001f49Smrg   endtest1 (glGetUniformLocationARB (prog, "FragmentUniform") != -1);
37332001f49Smrg
37432001f49Smrg   /*
37532001f49Smrg    * Query attrib location. Attribs with gl_ prefix cannot be queried.
37632001f49Smrg    * When gl_Vertex is used, none of the generic attribs can have index 0.
37732001f49Smrg    */
37832001f49Smrg   begintest (TT_PARAM1_NONZERO, "Query attrib location");
37932001f49Smrg   endtest1 (glGetAttribLocationARB (prog, "gl_Vertex") == -1);
38032001f49Smrg   endtest1 (glGetAttribLocationARB (prog, "AttribThatDoesNotExist") == -1);
38132001f49Smrg   endtest1 (glGetAttribLocationARB (prog, "") == -1);
38232001f49Smrg   endtest1 (glGetAttribLocationARB (prog, "FirstAttrib") > 0);
38332001f49Smrg   endtest1 (glGetAttribLocationARB (prog, "SecondAttrib") > 0);
38432001f49Smrg
38532001f49Smrg   /*
38632001f49Smrg    * Bind attrib locations, link and check if locations are correct.
38732001f49Smrg    */
38832001f49Smrg   begintest (TT_PARAM1_NONZERO, "Bind attrib location #1");
38932001f49Smrg   glBindAttribLocationARB (prog, 1, "FirstAttrib");
39032001f49Smrg   glBindAttribLocationARB (prog, 2, "SecondAttrib");
39132001f49Smrg   glLinkProgramARB (prog);
39232001f49Smrg   endtest1 (CheckObjectStatus (prog));
39332001f49Smrg   endtest1 (glGetAttribLocationARB (prog, "FirstAttrib") == 1);
39432001f49Smrg   endtest1 (glGetAttribLocationARB (prog, "SecondAttrib") == 2);
39532001f49Smrg
39632001f49Smrg   /*
39732001f49Smrg    * Bind attrib locations in different order. Link and check if locations are correct.
39832001f49Smrg    */
39932001f49Smrg   begintest (TT_PARAM1_NONZERO, "Bind attrib location #2");
40032001f49Smrg   glBindAttribLocationARB (prog, 1, "SecondAttrib");
40132001f49Smrg   glBindAttribLocationARB (prog, 2, "FirstAttrib");
40232001f49Smrg   glLinkProgramARB (prog);
40332001f49Smrg   endtest1 (CheckObjectStatus (prog));
40432001f49Smrg   endtest1 (glGetAttribLocationARB (prog, "SecondAttrib") == 1);
40532001f49Smrg   endtest1 (glGetAttribLocationARB (prog, "FirstAttrib") == 2);
40632001f49Smrg
40732001f49Smrg   /*
40832001f49Smrg    * Detach deleted object.
40932001f49Smrg    */
41032001f49Smrg   begintest (TT_GETERROR_NOERROR, "Detach deleted object");
41132001f49Smrg   glDetachObjectARB (prog, vert);
41232001f49Smrg   endtest ();
41332001f49Smrg   glDetachObjectARB (prog, frag);
41432001f49Smrg   endtest ();
41532001f49Smrg
41632001f49Smrg   /*
41732001f49Smrg    * Delete deleted detached object.
41832001f49Smrg    */
41932001f49Smrg   begintest (TT_GETERROR_INVALIDVALUE, "Delete deleted detached object");
42032001f49Smrg   glDeleteObjectARB (vert);
42132001f49Smrg   endtest ();
42232001f49Smrg   glDeleteObjectARB (frag);
42332001f49Smrg   endtest ();
42432001f49Smrg
42532001f49Smrg   exit (0);
42632001f49Smrg}
42732001f49Smrg
42832001f49Smrgvoid RenderScene (void)
42932001f49Smrg{
43032001f49Smrg   /* never reached */
43132001f49Smrg   assert (0);
43232001f49Smrg}
43332001f49Smrg
43432001f49Smrgint main (int argc, char *argv[])
43532001f49Smrg{
43632001f49Smrg   InitFramework (&argc, argv);
43732001f49Smrg   return 0;
43832001f49Smrg}
43932001f49Smrg
440