summaryrefslogtreecommitdiffstats
path: root/progs/slang/cltest.c
diff options
context:
space:
mode:
Diffstat (limited to 'progs/slang/cltest.c')
-rw-r--r--progs/slang/cltest.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/progs/slang/cltest.c b/progs/slang/cltest.c
new file mode 100644
index 00000000000..5736f3eab10
--- /dev/null
+++ b/progs/slang/cltest.c
@@ -0,0 +1,253 @@
+/*
+ * GL_ARB_shading_language_100 test application.
+ *
+ * Tests correctness of emited code. Runs multiple well-formed shaders and checks if
+ * they produce valid results.
+ *
+ * Requires specific support on the GL implementation side. A special function printMESA()
+ * must be supported in the language that prints current values of generic type
+ * to the appropriate shader's info log, and optionally to the screen.
+ *
+ * Author: Michal Krol
+ */
+
+#include "framework.h"
+
+#define EPSILON 0.0001f
+
+static GLhandleARB vert = 0;
+static GLhandleARB prog = 0;
+
+static int get_line (FILE *f, char *line, int size)
+{
+ if (fgets (line, size, f) == NULL)
+ return 0;
+ if (line[strlen (line) - 1] == '\n')
+ line[strlen (line) - 1] = '\0';
+ return 1;
+}
+
+struct ATTRIB
+{
+ char name[32];
+ GLfloat value[64][4];
+ GLuint count;
+};
+
+struct ATTRIBS
+{
+ struct ATTRIB attrib[32];
+ GLuint count;
+};
+
+struct SHADER
+{
+ char code[16000];
+ GLfloat output[1000];
+ GLuint count;
+};
+
+enum SHADER_LOAD_STATE
+{
+ SLS_NONE,
+ SLS_CODE,
+ SLS_OUTPUT
+};
+
+struct PROGRAM
+{
+ struct PROGRAM *next;
+ char name[256];
+ struct ATTRIBS attribs;
+ struct SHADER vertex;
+};
+
+enum PROGRAM_LOAD_STATE
+{
+ PLS_NONE,
+ PLS_ATTRIB,
+ PLS_VERTEX
+};
+
+static struct PROGRAM *program = NULL;
+
+static void load_test_file (const char *filename, struct PROGRAM **program)
+{
+ struct PROGRAM **currprog = program;
+ FILE *f;
+ char line[256];
+ enum PROGRAM_LOAD_STATE pls;
+ enum SHADER_LOAD_STATE sls;
+
+ f = fopen (filename, "r");
+ if (f == NULL)
+ return;
+
+ while (get_line (f, line, sizeof (line))) {
+ if (line[0] == '$') {
+ if (strncmp (line + 1, "program", 7) == 0) {
+ if (*currprog != NULL)
+ currprog = &(**currprog).next;
+ *currprog = (struct PROGRAM *) (malloc (sizeof (struct PROGRAM)));
+ if (*currprog == NULL)
+ break;
+ (**currprog).next = NULL;
+ strcpy ((**currprog).name, line + 9);
+ (**currprog).attribs.count = 0;
+ (**currprog).vertex.code[0] = '\0';
+ (**currprog).vertex.count = 0;
+ pls = PLS_NONE;
+ }
+ else if (strncmp (line + 1, "attrib", 6) == 0) {
+ if (*currprog == NULL)
+ break;
+ strcpy ((**currprog).attribs.attrib[(**currprog).attribs.count].name, line + 8);
+ (**currprog).attribs.attrib[(**currprog).attribs.count].count = 0;
+ (**currprog).attribs.count++;
+ pls = PLS_ATTRIB;
+ }
+ else if (strcmp (line + 1, "vertex") == 0) {
+ if (*currprog == NULL)
+ break;
+ pls = PLS_VERTEX;
+ sls = SLS_NONE;
+ }
+ else if (strcmp (line + 1, "code") == 0) {
+ if (*currprog == NULL || pls != PLS_VERTEX)
+ break;
+ sls = SLS_CODE;
+ }
+ else if (strcmp (line + 1, "output") == 0) {
+ if (*currprog == NULL || pls != PLS_VERTEX)
+ break;
+ sls = SLS_OUTPUT;
+ }
+ }
+ else {
+ if ((*currprog == NULL || pls == PLS_NONE || sls == SLS_NONE) && line[0] != '\0')
+ break;
+ if (*currprog != NULL && pls == PLS_VERTEX) {
+ if (sls == SLS_CODE) {
+ strcat ((**currprog).vertex.code, line);
+ strcat ((**currprog).vertex.code, "\n");
+ }
+ else if (sls == SLS_OUTPUT && line[0] != '\0') {
+ if (strcmp (line, "true") == 0)
+ (**currprog).vertex.output[(**currprog).vertex.count] = 1.0f;
+ else if (strcmp (line, "false") == 0)
+ (**currprog).vertex.output[(**currprog).vertex.count] = 0.0f;
+ else
+ sscanf (line, "%f", &(**currprog).vertex.output[(**currprog).vertex.count]);
+ (**currprog).vertex.count++;
+ }
+ }
+ else if (*currprog != NULL && pls == PLS_ATTRIB && line[0] != '\0') {
+ struct ATTRIB *att = &(**currprog).attribs.attrib[(**currprog).attribs.count - 1];
+ GLfloat *vec = att->value[att->count];
+ sscanf (line, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
+ att->count++;
+ }
+ }
+ }
+
+ fclose (f);
+}
+
+void InitScene (void)
+{
+ prog = glCreateProgramObjectARB ();
+ vert = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB);
+ glAttachObjectARB (prog, vert);
+ glDeleteObjectARB (vert);
+ load_test_file ("cltest.txt", &program);
+}
+
+void RenderScene (void)
+{
+ struct PROGRAM *nextprogram;
+ char *code;
+ GLint info_length, length;
+ char output[65000], *p;
+ GLuint i;
+
+ if (program == NULL)
+ exit (0);
+
+ code = program->vertex.code;
+ glShaderSourceARB (vert, 1, &code, NULL);
+ glCompileShaderARB (vert);
+ CheckObjectStatus (vert);
+
+ for (i = 0; i < program->attribs.count; i++) {
+ const char *name = program->attribs.attrib[i].name;
+ if (strcmp (name, "gl_Vertex") != 0)
+ glBindAttribLocationARB (prog, i, name);
+ }
+
+ glLinkProgramARB (prog);
+ CheckObjectStatus (prog);
+ glUseProgramObjectARB (prog);
+
+ printf ("\n--- %s\n", program->name);
+
+ glGetObjectParameterivARB (vert, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_length);
+
+ glBegin (GL_POINTS);
+ if (program->attribs.count == 0) {
+ glVertex2f (0.0f, 0.0f);
+ }
+ else {
+ for (i = 0; i < program->attribs.attrib[0].count; i++) {
+ GLuint j;
+ for (j = 0; j < program->attribs.count; j++) {
+ GLuint n = (j + 1) % program->attribs.count;
+ GLfloat *vec = program->attribs.attrib[n].value[i];
+ const char *name = program->attribs.attrib[n].name;
+ if (strcmp (name, "gl_Vertex") == 0)
+ glVertex4fv (vec);
+ else
+ glVertexAttrib4fvARB (n, vec);
+ }
+ }
+ }
+ glEnd ();
+ glFlush ();
+
+ glGetInfoLogARB (vert, sizeof (output), &length, output);
+ p = output + info_length - 1;
+ for (i = 0; i < program->vertex.count; i++) {
+ GLfloat value;
+ if (p == NULL) {
+ printf ("*** %s\n", "I/O error");
+ break;
+ }
+ if (strncmp (p, "true", 4) == 0)
+ value = 1.0f;
+ else if (strncmp (p, "false", 5) == 0)
+ value = 0.0f;
+ else if (sscanf (p, "%f", &value) != 1) {
+ printf ("*** %s\n", "I/O error");
+ break;
+ }
+ if (fabs (value - program->vertex.output[i]) > EPSILON) {
+ printf ("*** Values are different, is %f, should be %f\n", value,
+ program->vertex.output[i]);
+ }
+ p = strchr (p, '\n');
+ if (p != NULL)
+ p++;
+ }
+ if (*p != '\0')
+ printf ("*** %s\n", "I/O error");
+
+ nextprogram = program->next;
+ free (program);
+ program = nextprogram;
+}
+
+int main (int argc, char *argv[])
+{
+ InitFramework (&argc, argv);
+ return 0;
+}
+