diff options
Diffstat (limited to 'progs/tests/random.c')
-rw-r--r-- | progs/tests/random.c | 457 |
1 files changed, 457 insertions, 0 deletions
diff --git a/progs/tests/random.c b/progs/tests/random.c new file mode 100644 index 00000000000..d52c338e0e1 --- /dev/null +++ b/progs/tests/random.c @@ -0,0 +1,457 @@ +/** + * Random rendering, to check for crashes, hangs, etc. + * + * Brian Paul + * 21 June 2007 + */ + +#define GL_GLEXT_PROTOTYPES + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <GL/glut.h> + +static int Win; +static GLboolean Anim = GL_TRUE; +static int Width = 200, Height = 200; +static int DB = 0; +static int MinVertexCount = 0, MaxVertexCount = 1000; +static int Count = 0; + +struct vertex +{ + int type; + float v[4]; +}; + +static int BufferSize = 10000; +static struct vertex *Vbuffer = NULL; +static int Vcount, Vprim; + +enum { + BEGIN, + END, + VERTEX2, + VERTEX3, + VERTEX4, + COLOR3, + COLOR4, + TEX2, + TEX3, + TEX4, + SECCOLOR3, + NORMAL3 +}; + + + +/** + * This can be called from within gdb after a crash: + * (gdb) call ReportState() + */ +static void +ReportState(void) +{ + static const struct { + GLenum token; + char *str; + GLenum type; + } state [] = { + { GL_ALPHA_TEST, "GL_ALPHA_TEST", GL_INT }, + { GL_BLEND, "GL_BLEND", GL_INT }, + { GL_CLIP_PLANE0, "GL_CLIP_PLANE0", GL_INT }, + { GL_DEPTH_TEST, "GL_DEPTH_TEST", GL_INT }, + { GL_LIGHTING, "GL_LIGHTING", GL_INT }, + { GL_LINE_WIDTH, "GL_LINE_WIDTH", GL_FLOAT }, + { GL_POINT_SIZE, "GL_POINT_SIZE", GL_FLOAT }, + { GL_SHADE_MODEL, "GL_SHADE_MODEL", GL_INT }, + { GL_SCISSOR_TEST, "GL_SCISSOR_TEST", GL_INT }, + { 0, NULL, 0 } + }; + + GLint i; + + for (i = 0; state[i].token; i++) { + if (state[i].type == GL_INT) { + GLint v; + glGetIntegerv(state[i].token, &v); + printf("%s = %d\n", state[i].str, v); + } + else { + GLfloat v; + glGetFloatv(state[i].token, &v); + printf("%s = %f\n", state[i].str, v); + } + } +} + +static void +PrintVertex(const char *f, const struct vertex *v, int sz) +{ + int i; + printf("%s(", f); + for (i = 0; i < sz; i++) { + printf("%g%s", v->v[i], (i == sz-1) ? "" : ", "); + } + printf(");\n"); +} + +/** + * This can be called from within gdb after a crash: + * (gdb) call ReportState() + */ +static void +LastPrim(void) +{ + int i; + for (i = 0; i < Vcount; i++) { + switch (Vbuffer[i].type) { + case BEGIN: + printf("glBegin(%d);\n", (int) Vbuffer[i].v[0]); + break; + case END: + printf("glEnd();\n"); + break; + case VERTEX2: + PrintVertex("glVertex2f", Vbuffer + i, 2); + break; + case VERTEX3: + PrintVertex("glVertex3f", Vbuffer + i, 3); + break; + case VERTEX4: + PrintVertex("glVertex4f", Vbuffer + i, 4); + break; + case COLOR3: + PrintVertex("glColor3f", Vbuffer + i, 3); + break; + case COLOR4: + PrintVertex("glColor4f", Vbuffer + i, 4); + break; + case TEX2: + PrintVertex("glTexCoord2f", Vbuffer + i, 2); + break; + case TEX3: + PrintVertex("glTexCoord3f", Vbuffer + i, 3); + break; + case TEX4: + PrintVertex("glTexCoord4f", Vbuffer + i, 4); + break; + case SECCOLOR3: + PrintVertex("glSecondaryColor3f", Vbuffer + i, 3); + break; + case NORMAL3: + PrintVertex("glNormal3f", Vbuffer + i, 3); + break; + default: + abort(); + } + } +} + + +static int +RandomInt(int max) +{ + if (max == 0) + return 0; + return rand() % max; +} + +static float +RandomFloat(float min, float max) +{ + int k = rand() % 10000; + float x = min + (max - min) * k / 10000.0; + return x; +} + +/* + * Return true if random number in [0,1] is <= percentile. + */ +static GLboolean +RandomChoice(float percentile) +{ + return RandomFloat(0.0, 1.0) <= percentile; +} + +static void +RandomStateChange(void) +{ + int k = RandomInt(19); + switch (k) { + case 0: + glEnable(GL_BLEND); + break; + case 1: + glDisable(GL_BLEND); + break; + case 2: + glEnable(GL_ALPHA_TEST); + break; + case 3: + glEnable(GL_ALPHA_TEST); + break; + case 4: + glEnable(GL_DEPTH_TEST); + break; + case 5: + glEnable(GL_DEPTH_TEST); + break; + case 6: + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + break; + case 7: + glPointSize(10.0); + break; + case 8: + glPointSize(1.0); + break; + case 9: + glLineWidth(10.0); + break; + case 10: + glLineWidth(1.0); + break; + case 11: + glEnable(GL_LIGHTING); + break; + case 12: + glDisable(GL_LIGHTING); + break; + case 13: + glEnable(GL_SCISSOR_TEST); + break; + case 14: + glDisable(GL_SCISSOR_TEST); + break; + case 15: + glEnable(GL_CLIP_PLANE0); + break; + case 16: + glDisable(GL_CLIP_PLANE0); + break; + case 17: + glShadeModel(GL_FLAT); + break; + case 18: + glShadeModel(GL_SMOOTH); + break; + } +} + + +static void +RandomPrimitive(void) +{ + int i; + int len = MinVertexCount + RandomInt(MaxVertexCount - MinVertexCount); + + Vprim = RandomInt(10); + + glBegin(Vprim); + Vbuffer[Vcount].type = BEGIN; + Vbuffer[Vcount].v[0] = Vprim; + Vcount++; + + for (i = 0; i < len; i++) { + Vbuffer[Vcount].v[0] = RandomFloat(-3, 3); + Vbuffer[Vcount].v[1] = RandomFloat(-3, 3); + Vbuffer[Vcount].v[2] = RandomFloat(-3, 3); + Vbuffer[Vcount].v[3] = RandomFloat(-3, 3); + int k = RandomInt(9); + switch (k) { + case 0: + glVertex2fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = VERTEX2; + break; + case 1: + glVertex3fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = VERTEX3; + break; + case 2: + glVertex4fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = VERTEX4; + break; + case 3: + glColor3fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = COLOR3; + break; + case 4: + glColor4fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = COLOR4; + break; + case 5: + glTexCoord2fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = TEX2; + break; + case 6: + glTexCoord3fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = TEX3; + break; + case 7: + glTexCoord4fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = TEX4; + break; + case 8: + glSecondaryColor3fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = SECCOLOR3; + break; + case 9: + glNormal3fv(Vbuffer[Vcount].v); + Vbuffer[Vcount].type = NORMAL3; + break; + default: + abort(); + } + Vcount++; + + if (Vcount >= BufferSize - 2) { + /* reset */ + Vcount = 0; + } + } + + Vbuffer[Vcount++].type = END; + + glEnd(); +} + + +static void +RandomDraw(void) +{ + int i; + GLboolean dlist = RandomChoice(0.1); + if (dlist) + glNewList(1, GL_COMPILE); + for (i = 0; i < 3; i++) { + RandomStateChange(); + } + RandomPrimitive(); + + if (dlist) { + glEndList(); + glCallList(1); + } +} + + +static void +Idle(void) +{ + glutPostRedisplay(); +} + + +static void +Draw(void) +{ +#if 1 + RandomDraw(); + Count++; +#else + /* cut & paste temp code here */ +#endif + + assert(glGetError() == 0); + + if (DB) + glutSwapBuffers(); + else + glFinish(); +} + + +static void +Reshape(int width, int height) +{ + Width = width; + Height = height; + glViewport(0, 0, width, height); + glScissor(20, 20, Width-40, Height-40); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -15.0); +} + + +static void +Key(unsigned char key, int x, int y) +{ + (void) x; + (void) y; + switch (key) { + case 27: + glutDestroyWindow(Win); + exit(0); + break; + } + glutPostRedisplay(); +} + + +static void +Init(void) +{ + static const GLdouble plane[4] = {1, 1, 0, 0}; + glDrawBuffer(GL_FRONT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_LIGHT0); + glClipPlane(GL_CLIP_PLANE0, plane); + + Vbuffer = (struct vertex *) + malloc(BufferSize * sizeof(struct vertex)); + + /* silence warnings */ + (void) ReportState; + (void) LastPrim; +} + + +static void +ParseArgs(int argc, char *argv[]) +{ + int i; + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-s") == 0) { + int j = atoi(argv[i + 1]); + printf("Random seed value: %d\n", j); + srand(j); + i++; + } + else if (strcmp(argv[i], "-a") == 0) { + i++; + MinVertexCount = atoi(argv[i]); + } + else if (strcmp(argv[i], "-b") == 0) { + i++; + MaxVertexCount = atoi(argv[i]); + } + } +} + + +int +main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowPosition(0, 0); + glutInitWindowSize(Width, Height); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); + Win = glutCreateWindow(argv[0]); + ParseArgs(argc, argv); + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutDisplayFunc(Draw); + if (Anim) + glutIdleFunc(Idle); + Init(); + glutMainLoop(); + return 0; +} |