// // Simple Glut application that measures fill and polygon rate. #include #include #include /* for perror(3c) */ #include #include #include #include /* for sigset for forked X event handler process */ //#include /* for cmdline handler */ #include //#include #include #include #include #include #include //#include //#include //#include //#include //#include //#include /* for gethostname(2) */ //#include //#include //#include #include // Header File For The GLUT Library #include // Header File For The OpenGL32 Library #include // Header File For The GLu32 Library //#include // Header File for sleeping. //#include //#include //#include //#include /* ASCII code for the escape key. */ #define ESCAPE 27 #define LIMIT_MIN(val, min) if (val < (min)) val = min #define LIMIT_MAX(val, max) if (val > (max)) val = max #define LIMIT_MINMAX(val, min, max) LIMIT_MIN(val, min); LIMIT_MAX(val, max) #define LESSER(a, b, c) c = a < b ? a : b #define GREATER(a, b, c) c = a > b ? a : b #define DEBUG_MESSAGES 0 /* The number of our GLUT window */ int window; #define RAD2DEG(a) (a * 180.0 / M_PI) #define DEG2RAD(a) (a * M_PI / 180.0) #define SCREEN_X 800 #define SCREEN_Y 800 typedef struct _myOptions { char *fileName; } myOptions; typedef struct _mySharedData { myOptions *options; int mode; int done; char fileName[1024]; } mySharedData; mySharedData *shared; //pfuXFont smallfont; static double myTimeStamp ( void ); void print_file ( char *format, ... ) { va_list ap; char message[1024]; va_start ( ap, format ); vsprintf ( message, format, ap ); va_end ( ap ); if ( ! strlen ( shared->fileName ) ) { fprintf ( stderr, "BENCHMARK PLUGIN ERROR: fileName not configured.\n" ); return; } FILE *file = fopen ( shared->fileName, "a" ); if ( ! file ) { fprintf ( stderr, "BENCHMARK PLUGIN ERROR: cannot open %s for write.\n", shared->fileName ); return; } fputs ( message, file ); fclose ( file ); } static void clear_test ( int pixels ) { return; for ( int m=1; m<16; m++ ) { print_file ( "Pixel Clear Rate (" ); int mask = 0; if ( m & 1 ) { mask |= GL_COLOR_BUFFER_BIT; print_file ( "C" ); } else print_file ( "-" ); if ( m & 2 ) { mask |= GL_DEPTH_BUFFER_BIT; print_file ( "D" ); } else print_file ( "-" ); if ( m & 4 ) { mask |= GL_ACCUM_BUFFER_BIT; print_file ( "A" ); } else print_file ( "-" ); if ( m & 8 ) { mask |= GL_STENCIL_BUFFER_BIT; print_file ( "S" ); } else print_file ( "-" ); const int overlays = 100; glFinish(); double start = myTimeStamp(); for ( int i=0; ioptions = (myOptions*)malloc(sizeof(myOptions)); fprintf ( stderr, "BENCHMARK PLUGIN INFO: initialising\n" ); shared->done = 1; shared->mode = -1; static char filename[] = "benchresults.txt"; shared->options->fileName=(char*)filename;// (myOptions *) getPluginOptionBasePtr(); if ( shared->options->fileName ) strcpy ( shared->fileName, shared->options->fileName ); else { strcpy ( shared->fileName, hostname ); strcat ( shared->fileName, ".bench" ); } unlink ( shared->fileName ); time_t now; time ( &now ); struct tm *calender = localtime ( &now ); print_file ( "Date: %s", asctime ( calender ) ); print_file ( "Hostname: %s\n", hostname ); } if ( ! shared->options ) return 0; if ( frame_count < 400 ) return 0; if ( shared->done ) { if ( shared->mode < 35 ) { fprintf ( stderr, "BENCHMARK PLUGIN INFO: Collecting stats .... \n" ); shared->mode += 2; shared->done = 0; } else { print_file ( "\nMeasurements complete.\n" ); fprintf ( stderr, "BENCHMARK PLUGIN INFO: Terminating.\n" ); exit(0); } } #if DEBUG_MESSAGES fprintf ( stderr, "PLUGIN: PostAppCallBack end\n" ); #endif return 1; } int PostDrawCallBack ( unsigned int frame_count) { static int first = 1; const float yBase = 0.1f; const float xMargin = 0.1f; static int width, height, pixels; int s, texture; double PixelFillRate; #if DEBUG_MESSAGES fprintf ( stderr, "PLUGIN: PostDrawCallBack begin\n" ); #endif if ( ! shared ) return 0; if ( ! shared->options ) return 0; if ( first ) { width=SCREEN_X; height=SCREEN_Y; pixels = width * height; print_file ( "Renderer: %s\n", glGetString ( GL_RENDERER ) ); print_file ( "Vendor: %s\n", glGetString ( GL_VENDOR ) ); print_file ( "Version: %s\n", glGetString ( GL_VERSION ) ); print_file ( "\n\n" ); clear_test ( pixels ); first = 0; } // Mode bit 0 - enable benchmark if ( ! shared->mode & 1 || shared->done ) return 0; glMatrixMode ( GL_PROJECTION ); // Store old viewport settings and glPushMatrix(); // setup the channel and window to glLoadIdentity(); // a basic flat plane for drawing gluOrtho2D ( 0, 1, 0, 1 ); // 2D objects on glMatrixMode ( GL_MODELVIEW ); glPushMatrix(); glLoadIdentity(); //pfPushState(); //pfBasicState(); print_file ( "\n" ); // Mode bit 1 - depth test print_file ( "Z-buffer " ); if ( shared->mode & 0x2 ) { glEnable ( GL_DEPTH_TEST ); print_file ( "ON" ); } else { glDisable ( GL_DEPTH_TEST ); print_file ( "off" ); } // Mode bits 3:5 - 2D texture print_file ( ", Texture " ); texture = ( shared->mode & 0xF6 ) >> 2; if ( texture ) { glEnable ( GL_TEXTURE_2D ); switch ( texture ) { case 1: makeTexture ( 64 ); print_file ( "64x64" ); break; case 2: makeTexture ( 128 ); print_file ( "128x128" ); break; case 3: makeTexture ( 256 ); print_file ( "256x256" ); break; case 4: makeTexture ( 512 ); print_file ( "512x512" ); break; case 5: makeTexture ( 1024 ); print_file ( "1Kx1K" ); break; default: makeTexture ( 2048 ); print_file ( "2Kx2K" ); break; } } else { glDisable ( GL_TEXTURE_2D ); print_file ( "off" ); } PixelFillRate = pixel_fill ( pixels, texture ); print_file ( "\nPixel Fill Rate = %.2f Mpix/s\n", PixelFillRate / ( 1024 * 1024 ) ); for ( s = 3; s <= 10; s ++ ) { int tris = s - 2; double PolygonRate = poly ( s, texture ); double TriRate = PolygonRate * tris; print_file ( "%2d-sided Polygon Rate = %.2f Mpoly/s (%.2f Mtri/s)\n", s, PolygonRate / ( 1024 * 1024 ), TriRate / ( 1024 * 1024 ) ); } glEnable ( GL_LIGHTING ); glEnable ( GL_TEXTURE_2D ); glEnable ( GL_DEPTH_TEST ); //pfPopState(); // Retrieve old viewport setttings glMatrixMode ( GL_MODELVIEW ); // and return viewport to proper glPopMatrix(); // projection and view mode etc. glMatrixMode ( GL_PROJECTION ); glPopMatrix(); shared->done = 1; #if DEBUG_MESSAGES fprintf ( stderr, "PLUGIN: PostDrawCallBack end\n" ); #endif return 1; } /* The main drawing function. */ void DrawGLScene() { static int frame_count=0; PostAppCallBack ( frame_count ); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer // glLoadIdentity(); // Reset The View PostDrawCallBack ( frame_count); glutSwapBuffers(); frame_count++; } /* The function called whenever a key is pressed. */ void keyPressed(unsigned char key, int x, int y) { /* sleep to avoid thrashing this procedure */ Sleep(100); /* If escape is pressed, kill everything. */ if (key == ESCAPE) { /* shut down our window */ glutDestroyWindow(window); /* exit the program...normal termination. */ exit(0); } } int main(int argc, char **argv) { /* Initialize GLUT state - glut will take any command line arguments that pertain to it or X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */ glutInit(&argc, argv); /* Select type of Display mode: Double buffer RGBA color Alpha components supported Depth buffer */ glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA); /* get a x 480 window */ glutInitWindowSize(SCREEN_X, SCREEN_Y); /* the window starts at the upper left corner of the screen */ glutInitWindowPosition(0, 0); /* Open a window */ window = glutCreateWindow("Jeff Molofee's GL Code Tutorial ... NeHe '99"); /* Register the function to do all our OpenGL drawing. */ glutDisplayFunc(&DrawGLScene); /* Go fullscreen. This is as soon as possible. */ // glutFullScreen(); /* Even if there are no events, redraw our gl scene. */ glutIdleFunc(&DrawGLScene); /* Register the function called when our window is resized. */ // glutReshapeFunc(&ReSizeGLScene); /* Register the function called when the keyboard is pressed. */ // glutKeyboardFunc(&keyPressed); /* Initialize our window. */ InitGL(SCREEN_X, SCREEN_Y); /* Start Event Processing Engine */ glutMainLoop(); return 1; } static double myTimeStamp ( void ) { static long double perf_cnt; static int first = 1; static long double firstCount=0; if (first) { QueryPerformanceFrequency((LARGE_INTEGER *) &perf_cnt); QueryPerformanceCounter((LARGE_INTEGER *) &firstCount); first=0; } static long double thisCount; QueryPerformanceCounter((LARGE_INTEGER *) &thisCount); long double currentCount = thisCount - firstCount; return (double)(currentCount / perf_cnt); }