/* * This program is under the GNU GPL. * Use at your own risk. * * written by David Bucciarelli (tech.hmw@plus.it) * Humanware s.r.l. */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #include <GL/glut.h> typedef struct { char *name; char *unit; void (*init) (void); int (*run) (int, int); int type; int numsize; int size[10]; } benchmark; static int frontbuffer = 1; /***************************************************************************/ static void init_test01(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-0.5, 639.5, -0.5, 479.5); glMatrixMode(GL_MODELVIEW); glShadeModel(GL_FLAT); glDisable(GL_DEPTH_TEST); glClearColor(0.0, 0.1, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 0.0, 0.0); } static int test01(int size, int num) { int x, y; glBegin(GL_POINTS); for (y = 0; y < num; y++) for (x = 0; x < 480; x++) glVertex2i(x, x); glEnd(); return 480 * num; } /***************************************************************************/ static void init_test02(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-0.5, 639.5, -0.5, 479.5); glMatrixMode(GL_MODELVIEW); glShadeModel(GL_SMOOTH); glDisable(GL_DEPTH_TEST); glClearColor(0.0, 0.1, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); } static int test02(int size, int num) { int x, y; glBegin(GL_LINES); for (y = 0; y < num; y++) for (x = 0; x < size; x++) { glColor3f(0.0, 1.0, y / (float) num); glVertex2i(0, size - 1); glColor3f(1.0, 0.0, x / (float) size); glVertex2i(x, x); } glEnd(); return num * size; } /***************************************************************************/ static void init_test03(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-0.5, 639.5, -0.5, 479.5, 1.0, -1000.0 * 480.0); glMatrixMode(GL_MODELVIEW); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glClearColor(0.0, 0.1, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } static int test03(int size, int num) { int x, y, z; glBegin(GL_TRIANGLES); for (y = 0; y < num; y++) for (x = 0; x < size; x += 5) { z = num * size - (y * size + x); glColor3f(0.0, 1.0, 0.0); glVertex3i(0, x, z); glColor3f(1.0, 0.0, x / (float) size); glVertex3i(size - 1 - x, 0, z); glColor3f(1.0, x / (float) size, 0.0); glVertex3i(x, size - 1 - x, z); } glEnd(); return size * num / 5; } /***************************************************************************/ static void init_test04(void) { int x, y; GLubyte tex[128 * 128 * 3]; GLenum gluerr; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-0.5, 639.5, -0.5, 479.5, 1.0, -1000.0 * 480.0); glMatrixMode(GL_MODELVIEW); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for (y = 0; y < 128; y++) for (x = 0; x < 128; x++) { tex[(x + y * 128) * 3 + 0] = ((x % (128 / 4)) < (128 / 8)) ? 255 : 0; tex[(x + y * 128) * 3 + 1] = ((y % (128 / 4)) < (128 / 8)) ? 255 : 0; tex[(x + y * 128) * 3 + 2] = x; } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 128, 128, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *) (&tex[0])))) { fprintf(stderr, "GLULib%s\n", (char *) gluErrorString(gluerr)); exit(-1); } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_TEXTURE_2D); glClearColor(0.0, 0.1, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } static int test04(int size, int num) { int x, y, z; glBegin(GL_TRIANGLES); for (y = 0; y < num; y++) for (x = 0; x < size; x += 5) { z = num * size - (y * size + x); glTexCoord2f(1.0, 1.0); glColor3f(1.0, 0.0, 0.0); glVertex3i(0, x, z); glTexCoord2f(0.0, 1.0); glColor3f(0.0, 1.0, 0.0); glVertex3i(size - 1 - x, 0, z); glTexCoord2f(1.0, 0.0); glColor3f(0.0, 0.0, 1.0); glVertex3i(x, size - 1 - x, z); } glEnd(); return num * size / 5; } /***************************************************************************/ static void init_test05(void) { int x, y; GLubyte tex[128 * 128 * 3]; GLenum gluerr; glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); for (y = 0; y < 128; y++) for (x = 0; x < 128; x++) { tex[(x + y * 128) * 3 + 0] = ((x % (128 / 4)) < (128 / 8)) ? 255 : 0; tex[(x + y * 128) * 3 + 1] = ((y % (128 / 4)) < (128 / 8)) ? 255 : 0; tex[(x + y * 128) * 3 + 2] = x; } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if ((gluerr = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 128, 128, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *) (&tex[0])))) { fprintf(stderr, "GLULib%s\n", (char *) gluErrorString(gluerr)); exit(-1); } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_TEXTURE_2D); glDepthFunc(GL_ALWAYS); glClearColor(0.0, 0.1, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } static int test05(int size, int num) { int y; float v0[3], v1[3], v2[3], v3[3]; float cv0[3], cv1[3], cv2[3], cv3[3]; float tv0[3], tv1[3], tv2[3], tv3[3]; v0[0] = 320 - size / 2; v0[1] = 240 - size / 2; v0[2] = 0.0; v1[0] = 320 + size / 2; v1[1] = 240 - size / 2; v1[2] = 0.0; v2[0] = 320 - size / 2; v2[1] = 240 + size / 2; v2[2] = 0.0; v3[0] = 320 + size / 2; v3[1] = 240 + size / 2; v3[2] = 0.0; cv0[0] = 1.0; cv0[1] = 0.0; cv0[2] = 0.0; cv1[0] = 1.0; cv1[1] = 1.0; cv1[2] = 0.0; cv2[0] = 1.0; cv2[1] = 0.0; cv2[2] = 1.0; cv3[0] = 1.0; cv3[1] = 1.0; cv3[2] = 1.0; tv0[0] = 0.0; tv0[1] = 0.0; tv0[2] = 0.0; tv1[0] = 1.0; tv1[1] = 0.0; tv1[2] = 0.0; tv2[0] = 0.0; tv2[1] = 1.0; tv2[2] = 0.0; tv3[0] = 1.0; tv3[1] = 1.0; tv3[2] = 0.0; glBegin(GL_TRIANGLE_STRIP); for (y = 0; y < num; y++) { glColor3fv(cv0); glTexCoord2fv(tv0); glVertex3fv(v0); glColor3fv(cv1); glTexCoord2fv(tv1); glVertex3fv(v1); glColor3fv(cv2); glTexCoord2fv(tv2); glVertex3fv(v2); glColor3fv(cv3); glTexCoord2fv(tv3); glVertex3fv(v3); } glEnd(); return 4 * num - 2; } /***************************************************************************/ static void init_test06(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-0.5, 639.5, -0.5, 479.5); glMatrixMode(GL_MODELVIEW); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glClearColor(0.0, 0.1, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } static int test06(int size, int num) { int y; for (y = 0; y < num; y++) { glClearColor(y / (float) num, 0.1, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } return num; } /***************************************************************************/ #define BMARKS_TIME 5.0 #define NUM_BMARKS 6 /* 554 ~= sqrt(640*480) */ static benchmark bmarks[NUM_BMARKS] = { {"Simple Points", "Pnts", init_test01, test01, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, {"Smooth Lines", "Lins", init_test02, test02, 1, 5, {480, 250, 100, 50, 25, 0, 0, 0, 0, 0}}, {"ZSmooth Triangles", "Tris", init_test03, test03, 1, 5, {480, 250, 100, 50, 25, 0, 0, 0, 0, 0}}, {"ZSmooth Tex Blend Triangles", "Tris", init_test04, test04, 1, 5, {480, 250, 100, 50, 25, 0, 0, 0, 0, 0}}, {"ZSmooth Tex Blend TMesh Triangles", "Tris", init_test05, test05, 2, 8, {400, 250, 100, 50, 25, 10, 5, 2, 0, 0}}, {"Color/Depth Buffer Clears", "Clrs", init_test06, test06, 3, 0, {554, 0, 0, 0, 0, 0, 0, 0, 0, 0}} }; /***************************************************************************/ static void dotest0param(benchmark * bmark) { float stime, etime, dtime, tottime, maxtime, mintime; int num, numelem, calibnum, j; glPushAttrib(GL_ALL_ATTRIB_BITS); bmark->init(); stime = glutGet(GLUT_ELAPSED_TIME); dtime = 0.0; calibnum = 0; while (dtime < 2.0) { bmark->run(0, 1); glFinish(); etime = glutGet(GLUT_ELAPSED_TIME); dtime = (etime - stime) / 1000.0; calibnum++; } glPopAttrib(); fprintf(stderr, "Elapsed time for the calibration test (%d): %f\n", calibnum, dtime); num = (int) ((BMARKS_TIME / dtime) * calibnum); if (num < 1) num = 1; fprintf(stderr, "Selected number of benchmark iterations: %d\n", num); mintime = HUGE_VAL; maxtime = -HUGE_VAL; for (tottime = 0.0, j = 0; j < 5; j++) { glPushAttrib(GL_ALL_ATTRIB_BITS); bmark->init(); stime = glutGet(GLUT_ELAPSED_TIME); numelem = bmark->run(0, num); glFinish(); etime = glutGet(GLUT_ELAPSED_TIME); glPopAttrib(); dtime = (etime - stime) / 1000.0; tottime += dtime; fprintf(stderr, "Elapsed time for run %d: %f\n", j, dtime); if (dtime < mintime) mintime = dtime; if (dtime > maxtime) maxtime = dtime; } tottime -= mintime + maxtime; fprintf(stdout, "%s\n%f %s/sec", bmark->name, numelem / (tottime / 3.0), bmark->unit); if (bmark->type == 3) fprintf(stdout, ", MPixel Fill/sec: %f\n\n", (numelem * bmark->size[0] * (float) bmark->size[0]) / (1000000.0 * tottime / 3.0)); else fprintf(stdout, "\n\n"); } /***************************************************************************/ static void dotest1param(benchmark * bmark) { float stime, etime, dtime, tottime, maxtime, mintime; int num, numelem, calibnum, j, k; fprintf(stdout, "%s\n", bmark->name); for (j = 0; j < bmark->numsize; j++) { fprintf(stderr, "Current size: %d\n", bmark->size[j]); glPushAttrib(GL_ALL_ATTRIB_BITS); bmark->init(); stime = glutGet(GLUT_ELAPSED_TIME); dtime = 0.0; calibnum = 0; while (dtime < 2.0) { bmark->run(bmark->size[j], 1); glFinish(); etime = glutGet(GLUT_ELAPSED_TIME); dtime = (etime - stime) / 1000.0; calibnum++; } glPopAttrib(); fprintf(stderr, "Elapsed time for the calibration test (%d): %f\n", calibnum, dtime); num = (int) ((BMARKS_TIME / dtime) * calibnum); if (num < 1) num = 1; fprintf(stderr, "Selected number of benchmark iterations: %d\n", num); mintime = HUGE_VAL; maxtime = -HUGE_VAL; for (numelem = 1, tottime = 0.0, k = 0; k < 5; k++) { glPushAttrib(GL_ALL_ATTRIB_BITS); bmark->init(); stime = glutGet(GLUT_ELAPSED_TIME); numelem = bmark->run(bmark->size[j], num); glFinish(); etime = glutGet(GLUT_ELAPSED_TIME); glPopAttrib(); dtime = (etime - stime) / 1000.0; tottime += dtime; fprintf(stderr, "Elapsed time for run %d: %f\n", k, dtime); if (dtime < mintime) mintime = dtime; if (dtime > maxtime) maxtime = dtime; } tottime -= mintime + maxtime; fprintf(stdout, "SIZE=%03d => %f %s/sec", bmark->size[j], numelem / (tottime / 3.0), bmark->unit); if (bmark->type == 2) fprintf(stdout, ", MPixel Fill/sec: %f\n", (numelem * bmark->size[j] * bmark->size[j] / 2) / (1000000.0 * tottime / 3.0)); else fprintf(stdout, "\n"); } fprintf(stdout, "\n\n"); } /***************************************************************************/ static void display(void) { int i; if (frontbuffer) glDrawBuffer(GL_FRONT); else glDrawBuffer(GL_BACK); for (i = 0; i < NUM_BMARKS; i++) { fprintf(stderr, "Benchmark: %d\n", i); switch (bmarks[i].type) { case 0: case 3: dotest0param(&bmarks[i]); break; case 1: case 2: dotest1param(&bmarks[i]); break; } } exit(0); } int main(int ac, char **av) { fprintf(stderr, "GLTest v1.0\nWritten by David Bucciarelli\n"); if (ac == 2) frontbuffer = 0; glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowPosition(0, 0); glutInitWindowSize(640, 480); glutCreateWindow("OpenGL/Mesa Performances"); glutDisplayFunc(display); glutMainLoop(); return 0; }