132001f49Smrg/* 232001f49Smrg * GL_ARB_shading_language_100 test application. 332001f49Smrg * 432001f49Smrg * Tests correctness of emited code. Runs multiple well-formed shaders and checks if 532001f49Smrg * they produce valid results. 632001f49Smrg * 732001f49Smrg * Requires specific support on the GL implementation side. A special function printMESA() 832001f49Smrg * must be supported in the language that prints current values of generic type 932001f49Smrg * to the appropriate shader's info log, and optionally to the screen. 1032001f49Smrg * 1132001f49Smrg * Author: Michal Krol 1232001f49Smrg */ 1332001f49Smrg 1432001f49Smrg#include "framework.h" 1532001f49Smrg 1632001f49Smrg#define EPSILON 0.0001f 1732001f49Smrg 1832001f49Smrgstatic GLhandleARB vert = 0; 1932001f49Smrgstatic GLhandleARB prog = 0; 2032001f49Smrg 2132001f49Smrgstatic int get_line (FILE *f, char *line, int size) 2232001f49Smrg{ 2332001f49Smrg if (fgets (line, size, f) == NULL) 2432001f49Smrg return 0; 2532001f49Smrg if (line[strlen (line) - 1] == '\n') 2632001f49Smrg line[strlen (line) - 1] = '\0'; 2732001f49Smrg return 1; 2832001f49Smrg} 2932001f49Smrg 3032001f49Smrgstruct ATTRIB 3132001f49Smrg{ 3232001f49Smrg char name[32]; 3332001f49Smrg GLfloat value[64][4]; 3432001f49Smrg GLuint count; 3532001f49Smrg}; 3632001f49Smrg 3732001f49Smrgstruct ATTRIBS 3832001f49Smrg{ 3932001f49Smrg struct ATTRIB attrib[32]; 4032001f49Smrg GLuint count; 4132001f49Smrg}; 4232001f49Smrg 4332001f49Smrgstruct SHADER 4432001f49Smrg{ 4532001f49Smrg char code[16000]; 4632001f49Smrg GLfloat output[1000]; 4732001f49Smrg GLuint count; 4832001f49Smrg}; 4932001f49Smrg 5032001f49Smrgenum SHADER_LOAD_STATE 5132001f49Smrg{ 5232001f49Smrg SLS_NONE, 5332001f49Smrg SLS_CODE, 5432001f49Smrg SLS_OUTPUT 5532001f49Smrg}; 5632001f49Smrg 5732001f49Smrgstruct PROGRAM 5832001f49Smrg{ 5932001f49Smrg struct PROGRAM *next; 6032001f49Smrg char name[256]; 6132001f49Smrg struct ATTRIBS attribs; 6232001f49Smrg struct SHADER vertex; 6332001f49Smrg}; 6432001f49Smrg 6532001f49Smrgenum PROGRAM_LOAD_STATE 6632001f49Smrg{ 6732001f49Smrg PLS_NONE, 6832001f49Smrg PLS_ATTRIB, 6932001f49Smrg PLS_VERTEX 7032001f49Smrg}; 7132001f49Smrg 7232001f49Smrgstatic struct PROGRAM *program = NULL; 7332001f49Smrg 7432001f49Smrgstatic void load_test_file (const char *filename, struct PROGRAM **program) 7532001f49Smrg{ 7632001f49Smrg struct PROGRAM **currprog = program; 7732001f49Smrg FILE *f; 7832001f49Smrg char line[256]; 7932001f49Smrg enum PROGRAM_LOAD_STATE pls = PLS_NONE; 8032001f49Smrg enum SHADER_LOAD_STATE sls = SLS_NONE; 8132001f49Smrg 8232001f49Smrg f = fopen (filename, "r"); 8332001f49Smrg if (f == NULL) 8432001f49Smrg return; 8532001f49Smrg 8632001f49Smrg while (get_line (f, line, sizeof (line))) { 8732001f49Smrg if (line[0] == '$') { 8832001f49Smrg if (strncmp (line + 1, "program", 7) == 0) { 8932001f49Smrg if (*currprog != NULL) 9032001f49Smrg currprog = &(**currprog).next; 9132001f49Smrg *currprog = (struct PROGRAM *) (malloc (sizeof (struct PROGRAM))); 9232001f49Smrg if (*currprog == NULL) 9332001f49Smrg break; 9432001f49Smrg (**currprog).next = NULL; 9532001f49Smrg strcpy ((**currprog).name, line + 9); 9632001f49Smrg (**currprog).attribs.count = 0; 9732001f49Smrg (**currprog).vertex.code[0] = '\0'; 9832001f49Smrg (**currprog).vertex.count = 0; 9932001f49Smrg pls = PLS_NONE; 10032001f49Smrg } 10132001f49Smrg else if (strncmp (line + 1, "attrib", 6) == 0) { 10232001f49Smrg if (*currprog == NULL) 10332001f49Smrg break; 10432001f49Smrg strcpy ((**currprog).attribs.attrib[(**currprog).attribs.count].name, line + 8); 10532001f49Smrg (**currprog).attribs.attrib[(**currprog).attribs.count].count = 0; 10632001f49Smrg (**currprog).attribs.count++; 10732001f49Smrg pls = PLS_ATTRIB; 10832001f49Smrg } 10932001f49Smrg else if (strcmp (line + 1, "vertex") == 0) { 11032001f49Smrg if (*currprog == NULL) 11132001f49Smrg break; 11232001f49Smrg pls = PLS_VERTEX; 11332001f49Smrg sls = SLS_NONE; 11432001f49Smrg } 11532001f49Smrg else if (strcmp (line + 1, "code") == 0) { 11632001f49Smrg if (*currprog == NULL || pls != PLS_VERTEX) 11732001f49Smrg break; 11832001f49Smrg sls = SLS_CODE; 11932001f49Smrg } 12032001f49Smrg else if (strcmp (line + 1, "output") == 0) { 12132001f49Smrg if (*currprog == NULL || pls != PLS_VERTEX) 12232001f49Smrg break; 12332001f49Smrg sls = SLS_OUTPUT; 12432001f49Smrg } 12532001f49Smrg } 12632001f49Smrg else { 12732001f49Smrg if ((*currprog == NULL || pls == PLS_NONE || sls == SLS_NONE) && line[0] != '\0') 12832001f49Smrg break; 12932001f49Smrg if (*currprog != NULL && pls == PLS_VERTEX) { 13032001f49Smrg if (sls == SLS_CODE) { 13132001f49Smrg strcat ((**currprog).vertex.code, line); 13232001f49Smrg strcat ((**currprog).vertex.code, "\n"); 13332001f49Smrg } 13432001f49Smrg else if (sls == SLS_OUTPUT && line[0] != '\0') { 13532001f49Smrg if (strcmp (line, "true") == 0) 13632001f49Smrg (**currprog).vertex.output[(**currprog).vertex.count] = 1.0f; 13732001f49Smrg else if (strcmp (line, "false") == 0) 13832001f49Smrg (**currprog).vertex.output[(**currprog).vertex.count] = 0.0f; 13932001f49Smrg else 14032001f49Smrg sscanf (line, "%f", &(**currprog).vertex.output[(**currprog).vertex.count]); 14132001f49Smrg (**currprog).vertex.count++; 14232001f49Smrg } 14332001f49Smrg } 14432001f49Smrg else if (*currprog != NULL && pls == PLS_ATTRIB && line[0] != '\0') { 14532001f49Smrg struct ATTRIB *att = &(**currprog).attribs.attrib[(**currprog).attribs.count - 1]; 14632001f49Smrg GLfloat *vec = att->value[att->count]; 14732001f49Smrg sscanf (line, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]); 14832001f49Smrg att->count++; 14932001f49Smrg } 15032001f49Smrg } 15132001f49Smrg } 15232001f49Smrg 15332001f49Smrg fclose (f); 15432001f49Smrg} 15532001f49Smrg 15632001f49Smrgvoid InitScene (void) 15732001f49Smrg{ 15832001f49Smrg prog = glCreateProgramObjectARB (); 15932001f49Smrg vert = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB); 16032001f49Smrg glAttachObjectARB (prog, vert); 16132001f49Smrg glDeleteObjectARB (vert); 16232001f49Smrg load_test_file ("cltest.txt", &program); 16332001f49Smrg} 16432001f49Smrg 16532001f49Smrgvoid RenderScene (void) 16632001f49Smrg{ 16732001f49Smrg struct PROGRAM *nextprogram; 16832001f49Smrg char *code; 16932001f49Smrg GLint info_length, length; 17032001f49Smrg char output[65000], *p; 17132001f49Smrg GLuint i; 17232001f49Smrg 17332001f49Smrg if (program == NULL) 17432001f49Smrg exit (0); 17532001f49Smrg 17632001f49Smrg code = program->vertex.code; 17732001f49Smrg glShaderSourceARB (vert, 1, (const GLcharARB **) (&code), NULL); 17832001f49Smrg glCompileShaderARB (vert); 17932001f49Smrg CheckObjectStatus (vert); 18032001f49Smrg 18132001f49Smrg for (i = 0; i < program->attribs.count; i++) { 18232001f49Smrg const char *name = program->attribs.attrib[i].name; 18332001f49Smrg if (strcmp (name, "gl_Vertex") != 0) 18432001f49Smrg glBindAttribLocationARB (prog, i, name); 18532001f49Smrg } 18632001f49Smrg 18732001f49Smrg glLinkProgramARB (prog); 18832001f49Smrg CheckObjectStatus (prog); 18932001f49Smrg glUseProgramObjectARB (prog); 19032001f49Smrg 19132001f49Smrg printf ("\n--- %s\n", program->name); 19232001f49Smrg 19332001f49Smrg glGetObjectParameterivARB (vert, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_length); 19432001f49Smrg 19532001f49Smrg glBegin (GL_POINTS); 19632001f49Smrg if (program->attribs.count == 0) { 19732001f49Smrg glVertex2f (0.0f, 0.0f); 19832001f49Smrg } 19932001f49Smrg else { 20032001f49Smrg for (i = 0; i < program->attribs.attrib[0].count; i++) { 20132001f49Smrg GLuint j; 20232001f49Smrg for (j = 0; j < program->attribs.count; j++) { 20332001f49Smrg GLuint n = (j + 1) % program->attribs.count; 20432001f49Smrg GLfloat *vec = program->attribs.attrib[n].value[i]; 20532001f49Smrg const char *name = program->attribs.attrib[n].name; 20632001f49Smrg if (strcmp (name, "gl_Vertex") == 0) 20732001f49Smrg glVertex4fv (vec); 20832001f49Smrg else 20932001f49Smrg glVertexAttrib4fvARB (n, vec); 21032001f49Smrg } 21132001f49Smrg } 21232001f49Smrg } 21332001f49Smrg glEnd (); 21432001f49Smrg glFlush (); 21532001f49Smrg 21632001f49Smrg glGetInfoLogARB (vert, sizeof (output), &length, output); 21732001f49Smrg p = output + info_length - 1; 21832001f49Smrg for (i = 0; i < program->vertex.count; i++) { 21932001f49Smrg GLfloat value; 22032001f49Smrg if (p == NULL) { 22132001f49Smrg printf ("*** %s\n", "I/O error"); 22232001f49Smrg break; 22332001f49Smrg } 22432001f49Smrg if (strncmp (p, "true", 4) == 0) 22532001f49Smrg value = 1.0f; 22632001f49Smrg else if (strncmp (p, "false", 5) == 0) 22732001f49Smrg value = 0.0f; 22832001f49Smrg else if (sscanf (p, "%f", &value) != 1) { 22932001f49Smrg printf ("*** %s\n", "I/O error"); 23032001f49Smrg break; 23132001f49Smrg } 23232001f49Smrg if (fabs (value - program->vertex.output[i]) > EPSILON) { 23332001f49Smrg printf ("*** Values are different, is %f, should be %f\n", value, 23432001f49Smrg program->vertex.output[i]); 23532001f49Smrg } 23632001f49Smrg p = strchr (p, '\n'); 23732001f49Smrg if (p != NULL) 23832001f49Smrg p++; 23932001f49Smrg } 24032001f49Smrg if (p && *p != '\0') 24132001f49Smrg printf ("*** %s\n", "I/O error"); 24232001f49Smrg 24332001f49Smrg nextprogram = program->next; 24432001f49Smrg free (program); 24532001f49Smrg program = nextprogram; 24632001f49Smrg} 24732001f49Smrg 24832001f49Smrgint main (int argc, char *argv[]) 24932001f49Smrg{ 25032001f49Smrg InitFramework (&argc, argv); 25132001f49Smrg return 0; 25232001f49Smrg} 25332001f49Smrg 254