diff options
Diffstat (limited to 'progs/slang/sotest.c')
-rw-r--r-- | progs/slang/sotest.c | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/progs/slang/sotest.c b/progs/slang/sotest.c new file mode 100644 index 0000000..4bd3bc2 --- /dev/null +++ b/progs/slang/sotest.c @@ -0,0 +1,439 @@ +/* + * 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; +} + |