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