1/* 2 * GL_ARB_shading_language_100 test application. 3 * 4 * Tests correctness of emited code. Runs multiple well-formed shaders and checks if 5 * they produce valid results. 6 * 7 * Requires specific support on the GL implementation side. A special function printMESA() 8 * must be supported in the language that prints current values of generic type 9 * to the appropriate shader's info log, and optionally to the screen. 10 * 11 * Author: Michal Krol 12 */ 13 14#include "framework.h" 15 16#define EPSILON 0.0001f 17 18static GLhandleARB vert = 0; 19static GLhandleARB prog = 0; 20 21static int get_line (FILE *f, char *line, int size) 22{ 23 if (fgets (line, size, f) == NULL) 24 return 0; 25 if (line[strlen (line) - 1] == '\n') 26 line[strlen (line) - 1] = '\0'; 27 return 1; 28} 29 30struct ATTRIB 31{ 32 char name[32]; 33 GLfloat value[64][4]; 34 GLuint count; 35}; 36 37struct ATTRIBS 38{ 39 struct ATTRIB attrib[32]; 40 GLuint count; 41}; 42 43struct SHADER 44{ 45 char code[16000]; 46 GLfloat output[1000]; 47 GLuint count; 48}; 49 50enum SHADER_LOAD_STATE 51{ 52 SLS_NONE, 53 SLS_CODE, 54 SLS_OUTPUT 55}; 56 57struct PROGRAM 58{ 59 struct PROGRAM *next; 60 char name[256]; 61 struct ATTRIBS attribs; 62 struct SHADER vertex; 63}; 64 65enum PROGRAM_LOAD_STATE 66{ 67 PLS_NONE, 68 PLS_ATTRIB, 69 PLS_VERTEX 70}; 71 72static struct PROGRAM *program = NULL; 73 74static void load_test_file (const char *filename, struct PROGRAM **program) 75{ 76 struct PROGRAM **currprog = program; 77 FILE *f; 78 char line[256]; 79 enum PROGRAM_LOAD_STATE pls = PLS_NONE; 80 enum SHADER_LOAD_STATE sls = SLS_NONE; 81 82 f = fopen (filename, "r"); 83 if (f == NULL) 84 return; 85 86 while (get_line (f, line, sizeof (line))) { 87 if (line[0] == '$') { 88 if (strncmp (line + 1, "program", 7) == 0) { 89 if (*currprog != NULL) 90 currprog = &(**currprog).next; 91 *currprog = (struct PROGRAM *) (malloc (sizeof (struct PROGRAM))); 92 if (*currprog == NULL) 93 break; 94 (**currprog).next = NULL; 95 strcpy ((**currprog).name, line + 9); 96 (**currprog).attribs.count = 0; 97 (**currprog).vertex.code[0] = '\0'; 98 (**currprog).vertex.count = 0; 99 pls = PLS_NONE; 100 } 101 else if (strncmp (line + 1, "attrib", 6) == 0) { 102 if (*currprog == NULL) 103 break; 104 strcpy ((**currprog).attribs.attrib[(**currprog).attribs.count].name, line + 8); 105 (**currprog).attribs.attrib[(**currprog).attribs.count].count = 0; 106 (**currprog).attribs.count++; 107 pls = PLS_ATTRIB; 108 } 109 else if (strcmp (line + 1, "vertex") == 0) { 110 if (*currprog == NULL) 111 break; 112 pls = PLS_VERTEX; 113 sls = SLS_NONE; 114 } 115 else if (strcmp (line + 1, "code") == 0) { 116 if (*currprog == NULL || pls != PLS_VERTEX) 117 break; 118 sls = SLS_CODE; 119 } 120 else if (strcmp (line + 1, "output") == 0) { 121 if (*currprog == NULL || pls != PLS_VERTEX) 122 break; 123 sls = SLS_OUTPUT; 124 } 125 } 126 else { 127 if ((*currprog == NULL || pls == PLS_NONE || sls == SLS_NONE) && line[0] != '\0') 128 break; 129 if (*currprog != NULL && pls == PLS_VERTEX) { 130 if (sls == SLS_CODE) { 131 strcat ((**currprog).vertex.code, line); 132 strcat ((**currprog).vertex.code, "\n"); 133 } 134 else if (sls == SLS_OUTPUT && line[0] != '\0') { 135 if (strcmp (line, "true") == 0) 136 (**currprog).vertex.output[(**currprog).vertex.count] = 1.0f; 137 else if (strcmp (line, "false") == 0) 138 (**currprog).vertex.output[(**currprog).vertex.count] = 0.0f; 139 else 140 sscanf (line, "%f", &(**currprog).vertex.output[(**currprog).vertex.count]); 141 (**currprog).vertex.count++; 142 } 143 } 144 else if (*currprog != NULL && pls == PLS_ATTRIB && line[0] != '\0') { 145 struct ATTRIB *att = &(**currprog).attribs.attrib[(**currprog).attribs.count - 1]; 146 GLfloat *vec = att->value[att->count]; 147 sscanf (line, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]); 148 att->count++; 149 } 150 } 151 } 152 153 fclose (f); 154} 155 156void InitScene (void) 157{ 158 prog = glCreateProgramObjectARB (); 159 vert = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB); 160 glAttachObjectARB (prog, vert); 161 glDeleteObjectARB (vert); 162 load_test_file ("cltest.txt", &program); 163} 164 165void RenderScene (void) 166{ 167 struct PROGRAM *nextprogram; 168 char *code; 169 GLint info_length, length; 170 char output[65000], *p; 171 GLuint i; 172 173 if (program == NULL) 174 exit (0); 175 176 code = program->vertex.code; 177 glShaderSourceARB (vert, 1, (const GLcharARB **) (&code), NULL); 178 glCompileShaderARB (vert); 179 CheckObjectStatus (vert); 180 181 for (i = 0; i < program->attribs.count; i++) { 182 const char *name = program->attribs.attrib[i].name; 183 if (strcmp (name, "gl_Vertex") != 0) 184 glBindAttribLocationARB (prog, i, name); 185 } 186 187 glLinkProgramARB (prog); 188 CheckObjectStatus (prog); 189 glUseProgramObjectARB (prog); 190 191 printf ("\n--- %s\n", program->name); 192 193 glGetObjectParameterivARB (vert, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_length); 194 195 glBegin (GL_POINTS); 196 if (program->attribs.count == 0) { 197 glVertex2f (0.0f, 0.0f); 198 } 199 else { 200 for (i = 0; i < program->attribs.attrib[0].count; i++) { 201 GLuint j; 202 for (j = 0; j < program->attribs.count; j++) { 203 GLuint n = (j + 1) % program->attribs.count; 204 GLfloat *vec = program->attribs.attrib[n].value[i]; 205 const char *name = program->attribs.attrib[n].name; 206 if (strcmp (name, "gl_Vertex") == 0) 207 glVertex4fv (vec); 208 else 209 glVertexAttrib4fvARB (n, vec); 210 } 211 } 212 } 213 glEnd (); 214 glFlush (); 215 216 glGetInfoLogARB (vert, sizeof (output), &length, output); 217 p = output + info_length - 1; 218 for (i = 0; i < program->vertex.count; i++) { 219 GLfloat value; 220 if (p == NULL) { 221 printf ("*** %s\n", "I/O error"); 222 break; 223 } 224 if (strncmp (p, "true", 4) == 0) 225 value = 1.0f; 226 else if (strncmp (p, "false", 5) == 0) 227 value = 0.0f; 228 else if (sscanf (p, "%f", &value) != 1) { 229 printf ("*** %s\n", "I/O error"); 230 break; 231 } 232 if (fabs (value - program->vertex.output[i]) > EPSILON) { 233 printf ("*** Values are different, is %f, should be %f\n", value, 234 program->vertex.output[i]); 235 } 236 p = strchr (p, '\n'); 237 if (p != NULL) 238 p++; 239 } 240 if (p && *p != '\0') 241 printf ("*** %s\n", "I/O error"); 242 243 nextprogram = program->next; 244 free (program); 245 program = nextprogram; 246} 247 248int main (int argc, char *argv[]) 249{ 250 InitFramework (&argc, argv); 251 return 0; 252} 253 254