1/* 2 * GL_ARB_vertex_shader test application. Feeds a vertex shader with attributes that 3 * that have magic values and check if the values received by the shader are the same. 4 * 5 * Requires specific support on the GL implementation side. A special function printMESA() 6 * must be supported in the language that prints variable's current value of generic type 7 * to the appropriate shader's info log, and optionally to the screen. 8 * 9 * Perfectly valid behaviour produces output that does not have a line 10 * beginning with three stars (***). 11 * 12 * Author: Michal Krol 13 */ 14 15#include "framework.h" 16 17#define EPSILON 0.0001f 18 19static GLhandleARB vert = 0; 20static GLhandleARB prog = 0; 21 22enum SUBMIT_MODE 23{ 24 SM_IM, 25 SM_VA, 26 SM_IM_DL, 27 SM_VA_DL, 28 SM_MAX 29}; 30 31static enum SUBMIT_MODE submit_method = SM_IM; 32 33#define C 0 34#define S 1 35#define N 2 36#define V 3 37#define T 4 38#define F 5 39#define A 6 40 41struct ATTRIB_DATA 42{ 43 const char *name; 44 GLuint dispatch; 45 GLint index; 46 GLint bind; 47 GLuint size; 48 GLfloat data[4]; 49}; 50 51static struct ATTRIB_DATA attribs[] = { 52 { "gl_Color", C, -1, -1, 4, { 4.2f, 0.56f, -2.1f, 0.29f } }, 53 { "gl_SecondaryColor", S, -1, -1, 4, { 0.38f, 2.0f, 0.99f, 1.0f } }, 54 { "gl_Normal", N, -1, -1, 3, { 54.0f, 77.0f, 1.15f, 0.0f } }, 55 { "gl_MultiTexCoord0", T, 0, -1, 4, { 11.1f, 11.2f, 11.3f, 11.4f } }, 56 { "gl_MultiTexCoord1", T, 1, -1, 4, { 22.1f, 22.2f, 22.3f, 22.4f } }, 57 { "gl_MultiTexCoord2", T, 2, -1, 4, { 33.1f, 33.2f, 33.3f, 33.4f } }, 58 { "gl_MultiTexCoord3", T, 3, -1, 4, { 44.1f, 44.2f, 44.3f, 44.4f } }, 59 { "gl_MultiTexCoord4", T, 4, -1, 4, { 55.1f, 55.2f, 55.3f, 55.4f } }, 60 { "gl_MultiTexCoord5", T, 5, -1, 4, { 66.1f, 66.2f, 66.3f, 66.4f } }, 61 { "gl_MultiTexCoord6", T, 6, -1, 4, { 77.1f, 77.2f, 77.3f, 77.4f } }, 62 { "gl_MultiTexCoord7", T, 7, -1, 4, { 88.1f, 88.2f, 88.3f, 88.4f } }, 63 { "gl_FogCoord", F, -1, -1, 1, { 0.63f, 0.0f, 0.0f, 0.0f } }, 64 { "Attribute1", A, 1, 1, 4, { 1.11f, 1.22f, 1.33f, 1.44f } }, 65 { "Attribute2", A, 2, 2, 4, { 2.11f, 2.22f, 2.33f, 2.44f } }, 66 { "Attribute3", A, 3, 3, 4, { 3.11f, 3.22f, 3.33f, 3.44f } }, 67 { "Attribute4", A, 4, 4, 1, { 4.11f, 0.0f, 0.0f, 0.0f } }, 68 { "Attribute5", A, 5, 5, 2, { 5.11f, 5.22f, 0.0f, 0.0f } }, 69 { "Attribute6", A, 6, 6, 3, { 6.11f, 6.22f, 6.33f, 0.0f } }, 70 { "Attribute7", A, 7, 7, 2, { 7.11f, 7.22f, 0.0f, 0.0f } }, 71 { "Attribute7", A, 8, -1, 2, { 8.11f, 8.22f, 0.0f, 0.0f } }, 72 { "Attribute9", A, 9, 9, 3, { 9.11f, 9.22f, 9.33f, 0.0f } }, 73 { "Attribute9", A, 10, -1, 3, { 10.11f, 10.22f, 10.33f, 0.0f } }, 74 { "Attribute9", A, 11, -1, 3, { 11.11f, 11.22f, 11.33f, 0.0f } }, 75 { "Attribute12", A, 12, 12, 4, { 12.11f, 12.22f, 12.33f, 12.44f } }, 76 { "Attribute12", A, 13, -1, 4, { 13.11f, 13.22f, 13.33f, 13.44f } }, 77 { "Attribute12", A, 14, -1, 4, { 14.11f, 14.22f, 14.33f, 14.44f } }, 78 { "Attribute12", A, 15, -1, 4, { 15.11f, 15.22f, 15.33f, 15.44f } }, 79 { "gl_Vertex", V, 16, -1, 4, { 0.25f, -0.14f, 0.01f, 1.0f } } 80}; 81 82static void im_render (void) 83{ 84 GLint i; 85 86 glBegin (GL_POINTS); 87 for (i = 0; i < sizeof (attribs) / sizeof (*attribs); i++) { 88 struct ATTRIB_DATA *att = &attribs[i]; 89 switch (att->dispatch) 90 { 91 case C: 92 glColor4fv (att->data); 93 break; 94 case S: 95 glSecondaryColor3fvEXT (att->data); 96 break; 97 case N: 98 glNormal3fv (att->data); 99 break; 100 case V: 101 glVertex4fv (att->data); 102 break; 103 case T: 104 assert (att->index >= 0 && att->index < 8); 105 glMultiTexCoord4fvARB (GL_TEXTURE0_ARB + att->index, att->data); 106 break; 107 case F: 108 glFogCoordfvEXT (att->data); 109 break; 110 case A: 111 assert (att->index > 0 && att->index < 16); 112 glVertexAttrib4fvARB (att->index, att->data); 113 break; 114 default: 115 assert (0); 116 } 117 } 118 glEnd (); 119} 120 121static void va_render (void) 122{ 123 GLint i; 124 125 for (i = 0; i < sizeof (attribs) / sizeof (*attribs); i++) { 126 struct ATTRIB_DATA *att = &attribs[i]; 127 switch (att->dispatch) 128 { 129 case C: 130 glColorPointer (4, GL_FLOAT, 0, att->data); 131 glEnableClientState (GL_COLOR_ARRAY); 132 break; 133 case S: 134 glSecondaryColorPointerEXT (4, GL_FLOAT, 0, att->data); 135 glEnableClientState (GL_SECONDARY_COLOR_ARRAY_EXT); 136 break; 137 case N: 138 glNormalPointer (GL_FLOAT, 0, att->data); 139 glEnableClientState (GL_NORMAL_ARRAY); 140 break; 141 case V: 142 glVertexPointer (4, GL_FLOAT, 0, att->data); 143 glEnableClientState (GL_VERTEX_ARRAY); 144 break; 145 case T: 146 assert (att->index >= 0 && att->index < 8); 147 glClientActiveTextureARB (GL_TEXTURE0_ARB + att->index); 148 glTexCoordPointer (4, GL_FLOAT, 0, att->data); 149 glEnableClientState (GL_TEXTURE_COORD_ARRAY); 150 break; 151 case F: 152 glFogCoordPointerEXT (GL_FLOAT, 0, att->data); 153 glEnableClientState (GL_FOG_COORDINATE_ARRAY_EXT); 154 break; 155 case A: 156 assert (att->index > 0 && att->index < 16); 157 glVertexAttribPointerARB (att->index, 4, GL_FLOAT, GL_FALSE, 0, att->data); 158 glEnableVertexAttribArrayARB (att->index); 159 break; 160 default: 161 assert (0); 162 } 163 } 164 165 glDrawArrays (GL_POINTS, 0, 1); 166 167 for (i = 0; i < sizeof (attribs) / sizeof (*attribs); i++) { 168 struct ATTRIB_DATA *att = &attribs[i]; 169 switch (att->dispatch) 170 { 171 case C: 172 glDisableClientState (GL_COLOR_ARRAY); 173 break; 174 case S: 175 glDisableClientState (GL_SECONDARY_COLOR_ARRAY_EXT); 176 break; 177 case N: 178 glDisableClientState (GL_NORMAL_ARRAY); 179 break; 180 case V: 181 glDisableClientState (GL_VERTEX_ARRAY); 182 break; 183 case T: 184 glClientActiveTextureARB (GL_TEXTURE0_ARB + att->index); 185 glDisableClientState (GL_TEXTURE_COORD_ARRAY); 186 break; 187 case F: 188 glDisableClientState (GL_FOG_COORDINATE_ARRAY_EXT); 189 break; 190 case A: 191 glDisableVertexAttribArrayARB (att->index); 192 break; 193 default: 194 assert (0); 195 } 196 } 197} 198 199static void dl_start (void) 200{ 201 glNewList (GL_COMPILE, 1); 202} 203 204static void dl_end (void) 205{ 206 glEndList (); 207 glCallList (1); 208} 209 210static void load_test_file (const char *filename) 211{ 212 FILE *f; 213 GLint size; 214 char *code; 215 GLint i; 216 217 f = fopen (filename, "r"); 218 if (f == NULL) 219 return; 220 221 fseek (f, 0, SEEK_END); 222 size = ftell (f); 223 224 if (size == -1) { 225 fclose (f); 226 return; 227 } 228 229 fseek (f, 0, SEEK_SET); 230 231 code = (char *) (malloc (size)); 232 if (code == NULL) { 233 fclose (f); 234 return; 235 } 236 size = fread (code, 1, size, f); 237 fclose (f); 238 239 glShaderSourceARB (vert, 1, (const GLcharARB **) (&code), &size); 240 glCompileShaderARB (vert); 241 if (!CheckObjectStatus (vert)) 242 exit (0); 243 244 for (i = 0; i < sizeof (attribs) / sizeof (*attribs); i++) 245 if (attribs[i].dispatch == A && attribs[i].bind != -1) 246 glBindAttribLocationARB (prog, attribs[i].bind, attribs[i].name); 247} 248 249void InitScene (void) 250{ 251 prog = glCreateProgramObjectARB (); 252 vert = glCreateShaderObjectARB (GL_VERTEX_SHADER_ARB); 253 glAttachObjectARB (prog, vert); 254 glDeleteObjectARB (vert); 255 load_test_file ("vstest.txt"); 256 glLinkProgramARB (prog); 257 if (!CheckObjectStatus (prog)) 258 exit (0); 259 glUseProgramObjectARB (prog); 260} 261 262void RenderScene (void) 263{ 264 GLint info_length, length; 265 char output[65000], *p; 266 GLint i; 267 268 if (submit_method == SM_MAX) 269 exit (0); 270 271 /* 272 * Get the current size of the info log. Any text output produced by executed 273 * shader will be appended to the end of log. 274 */ 275 glGetObjectParameterivARB (vert, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_length); 276 277 switch (submit_method) 278 { 279 case SM_IM: 280 printf ("\n--- TESTING IMMEDIATE MODE\n"); 281 im_render (); 282 break; 283 case SM_VA: 284 printf ("\n--- TESTING VERTEX ARRAY MODE\n"); 285 va_render (); 286 break; 287 case SM_IM_DL: 288 printf ("\n--- TESTING IMMEDIATE + DISPLAY LIST MODE\n"); 289 dl_start (); 290 im_render (); 291 dl_end (); 292 break; 293 case SM_VA_DL: 294 printf ("\n--- TESTING VERTEX ARRAY + DISPLAY LIST MODE\n"); 295 dl_start (); 296 va_render (); 297 dl_end (); 298 break; 299 default: 300 assert (0); 301 } 302 303 glFlush (); 304 305 /* 306 * Get the info log and set the pointer to the beginning of the output. 307 */ 308 glGetInfoLogARB (vert, sizeof (output), &length, output); 309 p = output + info_length - 1; 310 311 for (i = 0; i < sizeof (attribs) / sizeof (*attribs); i++) { 312 GLuint j; 313 for (j = 0; j < attribs[i].size; j++) { 314 GLfloat value; 315 if (p == NULL) { 316 printf ("*** %s\n", "I/O error"); 317 break; 318 } 319 if (strncmp (p, "true", 4) == 0) 320 value = 1.0f; 321 else if (strncmp (p, "false", 5) == 0) 322 value = 0.0f; 323 else if (sscanf (p, "%f", &value) != 1) { 324 printf ("*** %s\n", "I/O error"); 325 p = NULL; 326 break; 327 } 328 if (fabs (value - attribs[i].data[j]) > EPSILON) 329 printf ("*** %s, is %f, should be %f\n", "Values are different", value, attribs[i].data[j]); 330 p = strchr (p, '\n'); 331 if (p != NULL) 332 p++; 333 } 334 if (p == NULL) 335 break; 336 } 337 338 submit_method++; 339} 340 341int main (int argc, char *argv[]) 342{ 343 InitFramework (&argc, argv); 344 return 0; 345} 346 347