/* * GL_ARB_shader_objects & GL_ARB_vertex_shader interface test application. * Neither compiler nor executor is being tested here, although some simple shader * compilation tests are performed. * * Perfectly valid behaviour produces output that does not have a line * beginning with three stars (***). * * Author: Michal Krol */ #include "framework.h" enum TEST_TYPE { TT_GETERROR_NOERROR, TT_GETERROR_INVALIDVALUE, TT_GETERROR_INVALIDOPERATION, TT_PARAM1_ZERO, TT_PARAM1_NONZERO }; static enum TEST_TYPE current_test; static void begintest (enum TEST_TYPE type, const char *name) { current_test = type; printf ("\n BEGIN TEST: %s\n", name); while (glGetError () != GL_NO_ERROR) ; } static void endtest1 (GLuint param1) { const char *msg = NULL; switch (current_test) { case TT_GETERROR_NOERROR: if (glGetError () != GL_NO_ERROR) msg = "glGetError () does not return GL_NO_ERROR"; break; case TT_GETERROR_INVALIDVALUE: if (glGetError () != GL_INVALID_VALUE) msg = "glGetError () does not return GL_INVALID_VALUE"; break; case TT_GETERROR_INVALIDOPERATION: if (glGetError () != GL_INVALID_OPERATION) msg = "glGetError () does not return GL_INVALID_OPERATION"; break; case TT_PARAM1_ZERO: if (param1) msg = "The parameter is not zero"; break; case TT_PARAM1_NONZERO: if (!param1) msg = "The parameter is not non-zero"; break; default: assert (0); } if (msg == NULL) printf (" OK\n"); else printf ("*** %s\n", msg); while (glGetError () != GL_NO_ERROR) ; } static void endtest () { endtest1 (0); } static GLhandleARB vert = 0; static GLhandleARB frag = 0; static GLhandleARB prog = 0; static GLhandleARB find_invalid_handle () { GLhandleARB handle; for (handle = 1; handle < 16; handle++) if (handle != vert && handle != frag && handle != prog) return handle; assert (0); return 0; } static const char *invsynvertsrc = "void main () {\n" " gl_Position = gl_ModelViewMatrix ! gl_Vertex;\n" /* unexpected token */ "}\n" ; static const char *invsemvertsrc = "void main () {\n" " gl_Position = gl_ModelviewMatrix * gl_Vertex;\n" /* undeclared identifier */ "}\n" ; static const char *uniforms = "uniform vec4 CommonUniform;\n" ; static const char *validvertsrc = "uniform vec4 VertexUniform;\n" "attribute vec4 FirstAttrib;\n" "attribute vec4 SecondAttrib;\n" "void main () {\n" " gl_Position = gl_ModelViewMatrix * gl_Vertex + CommonUniform + VertexUniform\n" " + FirstAttrib + SecondAttrib;\n" "}\n" ; static const char *invsynfragsrc = "void main () {\n" " gl_FragColor = gl_Color\n" /* missing ; */ "}\n" ; static const char *invsemfragsrc = "void main () {\n" " gl_FragColor = gl_FrontColor;\n" /* gl_FrontColor only in vertex shader */ "}\n" ; static const char *validfragsrc = "uniform vec4 FragmentUniform;\n" "void main () {\n" " gl_FragColor = gl_Color + CommonUniform + FragmentUniform;\n" "}\n" ; void InitScene (void) { GLint params[1]; const char *tab[2]; /* * GL should silently ignore calls that delete object 0. */ begintest (TT_GETERROR_NOERROR, "glDeleteObject(0)"); glDeleteObjectARB (0); endtest (); /* * GL generates an error on invalid object handle. */ begintest (TT_GETERROR_INVALIDVALUE, "Pass invalid non-zero object handle"); glDeleteObjectARB (find_invalid_handle ()); endtest (); glUseProgramObjectARB (find_invalid_handle ()); endtest (); /* * Create object. GL should return unique non-zero values. */ begintest (TT_PARAM1_NONZERO, "Create object"); vert = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB); endtest1 (vert); frag = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB); endtest1 (frag); prog = glCreateProgramObjectARB (); endtest1 (prog); endtest1 (vert != frag && frag != prog && prog != vert); /* * Link empty program. */ begintest (TT_PARAM1_NONZERO, "Link empty program"); glLinkProgramARB (prog); endtest1 (CheckObjectStatus (prog)); /* * Use empty program object. Empty program objects are valid. */ begintest (TT_GETERROR_NOERROR, "Use empty program object"); glUseProgramObjectARB (prog); endtest (); /* * Attach invalid object handles. Program object 0 should not be accepted. */ begintest (TT_GETERROR_INVALIDVALUE, "Attach invalid object handle"); glAttachObjectARB (0, find_invalid_handle ()); endtest (); glAttachObjectARB (0, frag); endtest (); glAttachObjectARB (find_invalid_handle (), find_invalid_handle ()); endtest (); glAttachObjectARB (find_invalid_handle (), frag); endtest (); glAttachObjectARB (prog, find_invalid_handle ()); endtest (); /* * Attach valid object handles with wrong semantics. */ begintest (TT_GETERROR_INVALIDOPERATION, "Attach object badly"); glAttachObjectARB (vert, frag); endtest (); glAttachObjectARB (vert, prog); endtest (); glAttachObjectARB (prog, prog); endtest (); /* * Detach non-attached object. */ begintest (TT_GETERROR_INVALIDOPERATION, "Detach non-attached object"); glDetachObjectARB (prog, vert); endtest (); glDetachObjectARB (prog, frag); endtest (); /* * Attach shader. */ begintest (TT_GETERROR_NOERROR, "Attach shader to program object"); glAttachObjectARB (prog, vert); endtest (); glAttachObjectARB (prog, frag); endtest (); /* * Attach object twice. */ begintest (TT_GETERROR_INVALIDOPERATION, "Attach object twice"); glAttachObjectARB (prog, vert); endtest (); glAttachObjectARB (prog, frag); endtest (); /* * Detach attached object. */ begintest (TT_GETERROR_NOERROR, "Detach attached object"); glDetachObjectARB (prog, vert); endtest (); glDetachObjectARB (prog, frag); endtest (); /* * Attach shader again. */ begintest (TT_GETERROR_NOERROR, "Attach shader again"); glAttachObjectARB (prog, vert); endtest (); glAttachObjectARB (prog, frag); endtest (); /* * Delete attached object. */ begintest (TT_GETERROR_NOERROR, "Delete attached object"); glDeleteObjectARB (vert); endtest (); glDeleteObjectARB (frag); endtest (); /* * Query delete status. It should return TRUE. Object handles are still valid * as they are referenced by program object container. */ begintest (TT_PARAM1_NONZERO, "Query delete status"); glGetObjectParameterivARB (vert, GL_OBJECT_DELETE_STATUS_ARB, params); endtest1 (params[0]); glGetObjectParameterivARB (frag, GL_OBJECT_DELETE_STATUS_ARB, params); endtest1 (params[0]); /* * Delete already deleted attached object. The behaviour is undefined, but we * check for no errors. The object still exists, so the handle value is okay. * In other words, these calls should be silently ignored by GL. */ begintest (TT_GETERROR_NOERROR, "Delete already deleted attached object"); glDeleteObjectARB (vert); endtest (); glDeleteObjectARB (frag); endtest (); /* * Compile shader source with syntax error. */ begintest (TT_PARAM1_ZERO, "Compile shader source with syntax error"); glShaderSourceARB (vert, 1, &invsynvertsrc, NULL); glCompileShaderARB (vert); endtest1 (CheckObjectStatus (vert)); glShaderSourceARB (frag, 1, &invsynfragsrc, NULL); glCompileShaderARB (frag); endtest1 (CheckObjectStatus (frag)); /* * Compile shader source with semantic error. */ begintest (TT_PARAM1_ZERO, "Compile shader source with semantic error"); glShaderSourceARB (vert, 1, &invsemvertsrc, NULL); glCompileShaderARB (vert); endtest1 (CheckObjectStatus (vert)); glShaderSourceARB (frag, 1, &invsemfragsrc, NULL); glCompileShaderARB (frag); endtest1 (CheckObjectStatus (frag)); /* * Link ill-formed vertex-fragment program. */ begintest (TT_PARAM1_ZERO, "Link ill-formed vertex-fragment program"); glLinkProgramARB (prog); endtest1 (CheckObjectStatus (prog)); /* * Use badly linked program object. */ begintest (TT_GETERROR_INVALIDOPERATION, "Use badly linked program object"); glUseProgramObjectARB (prog); endtest (); /* * Compile well-formed shader source. Check if multi-string sources can be handled. */ begintest (TT_PARAM1_NONZERO, "Compile well-formed shader source"); tab[0] = uniforms; tab[1] = validvertsrc; glShaderSourceARB (vert, 2, tab, NULL); glCompileShaderARB (vert); endtest1 (CheckObjectStatus (vert)); tab[0] = uniforms; tab[1] = validfragsrc; glShaderSourceARB (frag, 2, tab, NULL); glCompileShaderARB (frag); endtest1 (CheckObjectStatus (frag)); /* * Link vertex-fragment program. */ begintest (TT_PARAM1_NONZERO, "Link vertex-fragment program"); glLinkProgramARB (prog); endtest1 (CheckObjectStatus (prog)); /* * Use valid linked program object. */ begintest (TT_GETERROR_NOERROR, "Use linked program object"); glUseProgramObjectARB (prog); endtest (); /* * Get current program. */ begintest (TT_PARAM1_NONZERO, "Get current program"); endtest1 (glGetHandleARB (GL_PROGRAM_OBJECT_ARB) == prog); /* * Use 0 program object. */ begintest (TT_GETERROR_NOERROR, "Use 0 program object"); glUseProgramObjectARB (0); endtest (); /* * Query uniform location. Uniforms with gl_ prefix cannot be queried. */ begintest (TT_PARAM1_NONZERO, "Query uniform location"); endtest1 (glGetUniformLocationARB (prog, "gl_ModelViewMatrix") == -1); endtest1 (glGetUniformLocationARB (prog, "UniformThatDoesNotExist") == -1); endtest1 (glGetUniformLocationARB (prog, "") == -1); endtest1 (glGetUniformLocationARB (prog, "CommonUniform") != -1); endtest1 (glGetUniformLocationARB (prog, "VertexUniform") != -1); endtest1 (glGetUniformLocationARB (prog, "FragmentUniform") != -1); /* * Query attrib location. Attribs with gl_ prefix cannot be queried. * When gl_Vertex is used, none of the generic attribs can have index 0. */ begintest (TT_PARAM1_NONZERO, "Query attrib location"); endtest1 (glGetAttribLocationARB (prog, "gl_Vertex") == -1); endtest1 (glGetAttribLocationARB (prog, "AttribThatDoesNotExist") == -1); endtest1 (glGetAttribLocationARB (prog, "") == -1); endtest1 (glGetAttribLocationARB (prog, "FirstAttrib") > 0); endtest1 (glGetAttribLocationARB (prog, "SecondAttrib") > 0); /* * Bind attrib locations, link and check if locations are correct. */ begintest (TT_PARAM1_NONZERO, "Bind attrib location #1"); glBindAttribLocationARB (prog, 1, "FirstAttrib"); glBindAttribLocationARB (prog, 2, "SecondAttrib"); glLinkProgramARB (prog); endtest1 (CheckObjectStatus (prog)); endtest1 (glGetAttribLocationARB (prog, "FirstAttrib") == 1); endtest1 (glGetAttribLocationARB (prog, "SecondAttrib") == 2); /* * Bind attrib locations in different order. Link and check if locations are correct. */ begintest (TT_PARAM1_NONZERO, "Bind attrib location #2"); glBindAttribLocationARB (prog, 1, "SecondAttrib"); glBindAttribLocationARB (prog, 2, "FirstAttrib"); glLinkProgramARB (prog); endtest1 (CheckObjectStatus (prog)); endtest1 (glGetAttribLocationARB (prog, "SecondAttrib") == 1); endtest1 (glGetAttribLocationARB (prog, "FirstAttrib") == 2); /* * Detach deleted object. */ begintest (TT_GETERROR_NOERROR, "Detach deleted object"); glDetachObjectARB (prog, vert); endtest (); glDetachObjectARB (prog, frag); endtest (); /* * Delete deleted detached object. */ begintest (TT_GETERROR_INVALIDVALUE, "Delete deleted detached object"); glDeleteObjectARB (vert); endtest (); glDeleteObjectARB (frag); endtest (); exit (0); } void RenderScene (void) { /* never reached */ assert (0); } int main (int argc, char *argv[]) { InitFramework (&argc, argv); return 0; }