summaryrefslogtreecommitdiffstats
path: root/progs/slang/sotest.c
diff options
context:
space:
mode:
Diffstat (limited to 'progs/slang/sotest.c')
-rw-r--r--progs/slang/sotest.c439
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;
+}
+