132001f49Smrg/** 232001f49Smrg * Random rendering, to check for crashes, hangs, etc. 332001f49Smrg * 432001f49Smrg * Brian Paul 532001f49Smrg * 21 June 2007 632001f49Smrg */ 732001f49Smrg 832001f49Smrg 932001f49Smrg#include <assert.h> 1032001f49Smrg#include <stdio.h> 1132001f49Smrg#include <stdlib.h> 1232001f49Smrg#include <string.h> 1332001f49Smrg#include <math.h> 1432001f49Smrg#include <GL/glew.h> 1532001f49Smrg#include "glut_wrap.h" 1632001f49Smrg 1732001f49Smrgstatic int Win; 1832001f49Smrgstatic GLboolean Anim = GL_TRUE; 1932001f49Smrgstatic int Width = 200, Height = 200; 2032001f49Smrgstatic int DB = 0; 2132001f49Smrgstatic int MinVertexCount = 0, MaxVertexCount = 1000; 2232001f49Smrgstatic int Count = 0; 2332001f49Smrg 2432001f49Smrgstruct vertex 2532001f49Smrg{ 2632001f49Smrg int type; 2732001f49Smrg float v[4]; 2832001f49Smrg}; 2932001f49Smrg 3032001f49Smrgstatic int BufferSize = 10000; 3132001f49Smrgstatic struct vertex *Vbuffer = NULL; 3232001f49Smrgstatic int Vcount, Vprim; 3332001f49Smrg 3432001f49Smrgenum { 3532001f49Smrg BEGIN, 3632001f49Smrg END, 3732001f49Smrg VERTEX2, 3832001f49Smrg VERTEX3, 3932001f49Smrg VERTEX4, 4032001f49Smrg COLOR3, 4132001f49Smrg COLOR4, 4232001f49Smrg TEX2, 4332001f49Smrg TEX3, 4432001f49Smrg TEX4, 4532001f49Smrg SECCOLOR3, 4632001f49Smrg NORMAL3 4732001f49Smrg}; 4832001f49Smrg 4932001f49Smrg 5032001f49Smrg 5132001f49Smrg/** 5232001f49Smrg * This can be called from within gdb after a crash: 5332001f49Smrg * (gdb) call ReportState() 5432001f49Smrg */ 5532001f49Smrgstatic void 5632001f49SmrgReportState(void) 5732001f49Smrg{ 5832001f49Smrg static const struct { 5932001f49Smrg GLenum token; 6032001f49Smrg char *str; 6132001f49Smrg GLenum type; 6232001f49Smrg } state [] = { 6332001f49Smrg { GL_ALPHA_TEST, "GL_ALPHA_TEST", GL_INT }, 6432001f49Smrg { GL_BLEND, "GL_BLEND", GL_INT }, 6532001f49Smrg { GL_CLIP_PLANE0, "GL_CLIP_PLANE0", GL_INT }, 6632001f49Smrg { GL_DEPTH_TEST, "GL_DEPTH_TEST", GL_INT }, 6732001f49Smrg { GL_LIGHTING, "GL_LIGHTING", GL_INT }, 6832001f49Smrg { GL_LINE_WIDTH, "GL_LINE_WIDTH", GL_FLOAT }, 6932001f49Smrg { GL_POINT_SIZE, "GL_POINT_SIZE", GL_FLOAT }, 7032001f49Smrg { GL_SHADE_MODEL, "GL_SHADE_MODEL", GL_INT }, 7132001f49Smrg { GL_SCISSOR_TEST, "GL_SCISSOR_TEST", GL_INT }, 7232001f49Smrg { 0, NULL, 0 } 7332001f49Smrg }; 7432001f49Smrg 7532001f49Smrg GLint i; 7632001f49Smrg 7732001f49Smrg for (i = 0; state[i].token; i++) { 7832001f49Smrg if (state[i].type == GL_INT) { 7932001f49Smrg GLint v; 8032001f49Smrg glGetIntegerv(state[i].token, &v); 8132001f49Smrg printf("%s = %d\n", state[i].str, v); 8232001f49Smrg } 8332001f49Smrg else { 8432001f49Smrg GLfloat v; 8532001f49Smrg glGetFloatv(state[i].token, &v); 8632001f49Smrg printf("%s = %f\n", state[i].str, v); 8732001f49Smrg } 8832001f49Smrg } 8932001f49Smrg} 9032001f49Smrg 9132001f49Smrgstatic void 9232001f49SmrgPrintVertex(const char *f, const struct vertex *v, int sz) 9332001f49Smrg{ 9432001f49Smrg int i; 9532001f49Smrg printf("%s(", f); 9632001f49Smrg for (i = 0; i < sz; i++) { 9732001f49Smrg printf("%g%s", v->v[i], (i == sz-1) ? "" : ", "); 9832001f49Smrg } 9932001f49Smrg printf(");\n"); 10032001f49Smrg} 10132001f49Smrg 10232001f49Smrg/** 10332001f49Smrg * This can be called from within gdb after a crash: 10432001f49Smrg * (gdb) call ReportState() 10532001f49Smrg */ 10632001f49Smrgstatic void 10732001f49SmrgLastPrim(void) 10832001f49Smrg{ 10932001f49Smrg int i; 11032001f49Smrg for (i = 0; i < Vcount; i++) { 11132001f49Smrg switch (Vbuffer[i].type) { 11232001f49Smrg case BEGIN: 11332001f49Smrg printf("glBegin(%d);\n", (int) Vbuffer[i].v[0]); 11432001f49Smrg break; 11532001f49Smrg case END: 11632001f49Smrg printf("glEnd();\n"); 11732001f49Smrg break; 11832001f49Smrg case VERTEX2: 11932001f49Smrg PrintVertex("glVertex2f", Vbuffer + i, 2); 12032001f49Smrg break; 12132001f49Smrg case VERTEX3: 12232001f49Smrg PrintVertex("glVertex3f", Vbuffer + i, 3); 12332001f49Smrg break; 12432001f49Smrg case VERTEX4: 12532001f49Smrg PrintVertex("glVertex4f", Vbuffer + i, 4); 12632001f49Smrg break; 12732001f49Smrg case COLOR3: 12832001f49Smrg PrintVertex("glColor3f", Vbuffer + i, 3); 12932001f49Smrg break; 13032001f49Smrg case COLOR4: 13132001f49Smrg PrintVertex("glColor4f", Vbuffer + i, 4); 13232001f49Smrg break; 13332001f49Smrg case TEX2: 13432001f49Smrg PrintVertex("glTexCoord2f", Vbuffer + i, 2); 13532001f49Smrg break; 13632001f49Smrg case TEX3: 13732001f49Smrg PrintVertex("glTexCoord3f", Vbuffer + i, 3); 13832001f49Smrg break; 13932001f49Smrg case TEX4: 14032001f49Smrg PrintVertex("glTexCoord4f", Vbuffer + i, 4); 14132001f49Smrg break; 14232001f49Smrg case SECCOLOR3: 14332001f49Smrg PrintVertex("glSecondaryColor3f", Vbuffer + i, 3); 14432001f49Smrg break; 14532001f49Smrg case NORMAL3: 14632001f49Smrg PrintVertex("glNormal3f", Vbuffer + i, 3); 14732001f49Smrg break; 14832001f49Smrg default: 14932001f49Smrg abort(); 15032001f49Smrg } 15132001f49Smrg } 15232001f49Smrg} 15332001f49Smrg 15432001f49Smrg 15532001f49Smrgstatic int 15632001f49SmrgRandomInt(int max) 15732001f49Smrg{ 15832001f49Smrg if (max == 0) 15932001f49Smrg return 0; 16032001f49Smrg return rand() % max; 16132001f49Smrg} 16232001f49Smrg 16332001f49Smrgstatic float 16432001f49SmrgRandomFloat(float min, float max) 16532001f49Smrg{ 16632001f49Smrg int k = rand() % 10000; 16732001f49Smrg float x = min + (max - min) * k / 10000.0; 16832001f49Smrg return x; 16932001f49Smrg} 17032001f49Smrg 17132001f49Smrg/* 17232001f49Smrg * Return true if random number in [0,1] is <= percentile. 17332001f49Smrg */ 17432001f49Smrgstatic GLboolean 17532001f49SmrgRandomChoice(float percentile) 17632001f49Smrg{ 17732001f49Smrg return RandomFloat(0.0, 1.0) <= percentile; 17832001f49Smrg} 17932001f49Smrg 18032001f49Smrgstatic void 18132001f49SmrgRandomStateChange(void) 18232001f49Smrg{ 18332001f49Smrg int k = RandomInt(19); 18432001f49Smrg switch (k) { 18532001f49Smrg case 0: 18632001f49Smrg glEnable(GL_BLEND); 18732001f49Smrg break; 18832001f49Smrg case 1: 18932001f49Smrg glDisable(GL_BLEND); 19032001f49Smrg break; 19132001f49Smrg case 2: 19232001f49Smrg glEnable(GL_ALPHA_TEST); 19332001f49Smrg break; 19432001f49Smrg case 3: 19532001f49Smrg glEnable(GL_ALPHA_TEST); 19632001f49Smrg break; 19732001f49Smrg case 4: 19832001f49Smrg glEnable(GL_DEPTH_TEST); 19932001f49Smrg break; 20032001f49Smrg case 5: 20132001f49Smrg glEnable(GL_DEPTH_TEST); 20232001f49Smrg break; 20332001f49Smrg case 6: 20432001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 20532001f49Smrg break; 20632001f49Smrg case 7: 20732001f49Smrg glPointSize(10.0); 20832001f49Smrg break; 20932001f49Smrg case 8: 21032001f49Smrg glPointSize(1.0); 21132001f49Smrg break; 21232001f49Smrg case 9: 21332001f49Smrg glLineWidth(10.0); 21432001f49Smrg break; 21532001f49Smrg case 10: 21632001f49Smrg glLineWidth(1.0); 21732001f49Smrg break; 21832001f49Smrg case 11: 21932001f49Smrg glEnable(GL_LIGHTING); 22032001f49Smrg break; 22132001f49Smrg case 12: 22232001f49Smrg glDisable(GL_LIGHTING); 22332001f49Smrg break; 22432001f49Smrg case 13: 22532001f49Smrg glEnable(GL_SCISSOR_TEST); 22632001f49Smrg break; 22732001f49Smrg case 14: 22832001f49Smrg glDisable(GL_SCISSOR_TEST); 22932001f49Smrg break; 23032001f49Smrg case 15: 23132001f49Smrg glEnable(GL_CLIP_PLANE0); 23232001f49Smrg break; 23332001f49Smrg case 16: 23432001f49Smrg glDisable(GL_CLIP_PLANE0); 23532001f49Smrg break; 23632001f49Smrg case 17: 23732001f49Smrg glShadeModel(GL_FLAT); 23832001f49Smrg break; 23932001f49Smrg case 18: 24032001f49Smrg glShadeModel(GL_SMOOTH); 24132001f49Smrg break; 24232001f49Smrg } 24332001f49Smrg} 24432001f49Smrg 24532001f49Smrg 24632001f49Smrgstatic void 24732001f49SmrgRandomPrimitive(void) 24832001f49Smrg{ 24932001f49Smrg int i; 25032001f49Smrg int len = MinVertexCount + RandomInt(MaxVertexCount - MinVertexCount); 25132001f49Smrg 25232001f49Smrg Vprim = RandomInt(10); 25332001f49Smrg 25432001f49Smrg glBegin(Vprim); 25532001f49Smrg Vbuffer[Vcount].type = BEGIN; 25632001f49Smrg Vbuffer[Vcount].v[0] = Vprim; 25732001f49Smrg Vcount++; 25832001f49Smrg 25932001f49Smrg for (i = 0; i < len; i++) { 26032001f49Smrg int k = RandomInt(9); 26132001f49Smrg Vbuffer[Vcount].v[0] = RandomFloat(-3, 3); 26232001f49Smrg Vbuffer[Vcount].v[1] = RandomFloat(-3, 3); 26332001f49Smrg Vbuffer[Vcount].v[2] = RandomFloat(-3, 3); 26432001f49Smrg Vbuffer[Vcount].v[3] = RandomFloat(-3, 3); 26532001f49Smrg switch (k) { 26632001f49Smrg case 0: 26732001f49Smrg glVertex2fv(Vbuffer[Vcount].v); 26832001f49Smrg Vbuffer[Vcount].type = VERTEX2; 26932001f49Smrg break; 27032001f49Smrg case 1: 27132001f49Smrg glVertex3fv(Vbuffer[Vcount].v); 27232001f49Smrg Vbuffer[Vcount].type = VERTEX3; 27332001f49Smrg break; 27432001f49Smrg case 2: 27532001f49Smrg glVertex4fv(Vbuffer[Vcount].v); 27632001f49Smrg Vbuffer[Vcount].type = VERTEX4; 27732001f49Smrg break; 27832001f49Smrg case 3: 27932001f49Smrg glColor3fv(Vbuffer[Vcount].v); 28032001f49Smrg Vbuffer[Vcount].type = COLOR3; 28132001f49Smrg break; 28232001f49Smrg case 4: 28332001f49Smrg glColor4fv(Vbuffer[Vcount].v); 28432001f49Smrg Vbuffer[Vcount].type = COLOR4; 28532001f49Smrg break; 28632001f49Smrg case 5: 28732001f49Smrg glTexCoord2fv(Vbuffer[Vcount].v); 28832001f49Smrg Vbuffer[Vcount].type = TEX2; 28932001f49Smrg break; 29032001f49Smrg case 6: 29132001f49Smrg glTexCoord3fv(Vbuffer[Vcount].v); 29232001f49Smrg Vbuffer[Vcount].type = TEX3; 29332001f49Smrg break; 29432001f49Smrg case 7: 29532001f49Smrg glTexCoord4fv(Vbuffer[Vcount].v); 29632001f49Smrg Vbuffer[Vcount].type = TEX4; 29732001f49Smrg break; 29832001f49Smrg case 8: 29932001f49Smrg glSecondaryColor3fv(Vbuffer[Vcount].v); 30032001f49Smrg Vbuffer[Vcount].type = SECCOLOR3; 30132001f49Smrg break; 30232001f49Smrg case 9: 30332001f49Smrg glNormal3fv(Vbuffer[Vcount].v); 30432001f49Smrg Vbuffer[Vcount].type = NORMAL3; 30532001f49Smrg break; 30632001f49Smrg default: 30732001f49Smrg abort(); 30832001f49Smrg } 30932001f49Smrg Vcount++; 31032001f49Smrg 31132001f49Smrg if (Vcount >= BufferSize - 2) { 31232001f49Smrg /* reset */ 31332001f49Smrg Vcount = 0; 31432001f49Smrg } 31532001f49Smrg } 31632001f49Smrg 31732001f49Smrg Vbuffer[Vcount++].type = END; 31832001f49Smrg 31932001f49Smrg glEnd(); 32032001f49Smrg} 32132001f49Smrg 32232001f49Smrg 32332001f49Smrgstatic void 32432001f49SmrgRandomDraw(void) 32532001f49Smrg{ 32632001f49Smrg int i; 32732001f49Smrg GLboolean dlist = RandomChoice(0.1); 32832001f49Smrg if (dlist) 32932001f49Smrg glNewList(1, GL_COMPILE); 33032001f49Smrg for (i = 0; i < 3; i++) { 33132001f49Smrg RandomStateChange(); 33232001f49Smrg } 33332001f49Smrg RandomPrimitive(); 33432001f49Smrg 33532001f49Smrg if (dlist) { 33632001f49Smrg glEndList(); 33732001f49Smrg glCallList(1); 33832001f49Smrg } 33932001f49Smrg} 34032001f49Smrg 34132001f49Smrg 34232001f49Smrgstatic void 34332001f49SmrgIdle(void) 34432001f49Smrg{ 34532001f49Smrg glutPostRedisplay(); 34632001f49Smrg} 34732001f49Smrg 34832001f49Smrg 34932001f49Smrgstatic void 35032001f49SmrgDraw(void) 35132001f49Smrg{ 35232001f49Smrg#if 1 35332001f49Smrg RandomDraw(); 35432001f49Smrg Count++; 35532001f49Smrg#else 35632001f49Smrg /* cut & paste temp code here */ 35732001f49Smrg#endif 35832001f49Smrg 35932001f49Smrg assert(glGetError() == 0); 36032001f49Smrg 36132001f49Smrg if (DB) 36232001f49Smrg glutSwapBuffers(); 36332001f49Smrg else 36432001f49Smrg glFinish(); 36532001f49Smrg} 36632001f49Smrg 36732001f49Smrg 36832001f49Smrgstatic void 36932001f49SmrgReshape(int width, int height) 37032001f49Smrg{ 37132001f49Smrg Width = width; 37232001f49Smrg Height = height; 37332001f49Smrg glViewport(0, 0, width, height); 37432001f49Smrg glScissor(20, 20, Width-40, Height-40); 37532001f49Smrg glMatrixMode(GL_PROJECTION); 37632001f49Smrg glLoadIdentity(); 37732001f49Smrg glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); 37832001f49Smrg glMatrixMode(GL_MODELVIEW); 37932001f49Smrg glLoadIdentity(); 38032001f49Smrg glTranslatef(0.0, 0.0, -15.0); 38132001f49Smrg} 38232001f49Smrg 38332001f49Smrg 38432001f49Smrgstatic void 38532001f49SmrgKey(unsigned char key, int x, int y) 38632001f49Smrg{ 38732001f49Smrg (void) x; 38832001f49Smrg (void) y; 38932001f49Smrg switch (key) { 39032001f49Smrg case 27: 39132001f49Smrg glutDestroyWindow(Win); 39232001f49Smrg exit(0); 39332001f49Smrg break; 39432001f49Smrg } 39532001f49Smrg glutPostRedisplay(); 39632001f49Smrg} 39732001f49Smrg 39832001f49Smrg 39932001f49Smrgstatic void 40032001f49SmrgInit(void) 40132001f49Smrg{ 40232001f49Smrg static const GLdouble plane[4] = {1, 1, 0, 0}; 40332001f49Smrg glDrawBuffer(GL_FRONT); 40432001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 40532001f49Smrg glEnable(GL_LIGHT0); 40632001f49Smrg glClipPlane(GL_CLIP_PLANE0, plane); 40732001f49Smrg 40832001f49Smrg Vbuffer = (struct vertex *) 40932001f49Smrg malloc(BufferSize * sizeof(struct vertex)); 41032001f49Smrg 41132001f49Smrg /* silence warnings */ 41232001f49Smrg (void) ReportState; 41332001f49Smrg (void) LastPrim; 41432001f49Smrg} 41532001f49Smrg 41632001f49Smrg 41732001f49Smrgstatic void 41832001f49SmrgParseArgs(int argc, char *argv[]) 41932001f49Smrg{ 42032001f49Smrg int i; 42132001f49Smrg for (i = 1; i < argc; i++) { 42232001f49Smrg if (strcmp(argv[i], "-s") == 0) { 42332001f49Smrg int j = atoi(argv[i + 1]); 42432001f49Smrg printf("Random seed value: %d\n", j); 42532001f49Smrg srand(j); 42632001f49Smrg i++; 42732001f49Smrg } 42832001f49Smrg else if (strcmp(argv[i], "-a") == 0) { 42932001f49Smrg i++; 43032001f49Smrg MinVertexCount = atoi(argv[i]); 43132001f49Smrg } 43232001f49Smrg else if (strcmp(argv[i], "-b") == 0) { 43332001f49Smrg i++; 43432001f49Smrg MaxVertexCount = atoi(argv[i]); 43532001f49Smrg } 43632001f49Smrg } 43732001f49Smrg} 43832001f49Smrg 43932001f49Smrg 44032001f49Smrgint 44132001f49Smrgmain(int argc, char *argv[]) 44232001f49Smrg{ 44332001f49Smrg glutInit(&argc, argv); 44432001f49Smrg glutInitWindowPosition(0, 0); 44532001f49Smrg glutInitWindowSize(Width, Height); 44632001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); 44732001f49Smrg Win = glutCreateWindow(argv[0]); 44832001f49Smrg glewInit(); 44932001f49Smrg ParseArgs(argc, argv); 45032001f49Smrg glutReshapeFunc(Reshape); 45132001f49Smrg glutKeyboardFunc(Key); 45232001f49Smrg glutDisplayFunc(Draw); 45332001f49Smrg if (Anim) 45432001f49Smrg glutIdleFunc(Idle); 45532001f49Smrg Init(); 45632001f49Smrg glutMainLoop(); 45732001f49Smrg return 0; 45832001f49Smrg} 459