/***************************************************************************** cc -o fractal -O fractal.c -lGLU -lGL -lX11 -mp **********************************************************************/ /* B */ /* ACS 388 Final Project */ /* SGI Fractal algorithm */ /***************************************/ #include #include #include #include #include #include #include #include #include #define mywidth 1000 #define myheight 1000 const int maxcol = 1000; const int maxrow = 1000; int max_iterations = 512; int max_size = 4; int LINEWIDTH=1, OPERATOR=0x00, ANGLE, XCENTER, YCENTER; float Q[1024]; float XMax, YMax, XMin, YMin; int mybuffer[1000][2]; char* ApplicationName; double Overhead = 0.0; int VisualAttributes[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, None }; int WindowWidth; int WindowHeight; void Fractal(void); void showtime(timespec_t); /********************************************************************** * GetClock - get current time (expressed in seconds) **********************************************************************/ double GetClock(void) { struct timeval t; gettimeofday(&t); return (double) t.tv_sec + (double) t.tv_usec * 1E-6; } /********************************************************************** * ChooseRunTime - select an appropriate runtime for benchmarking **********************************************************************/ double ChooseRunTime(void) { double start; double finish; double runTime; start = GetClock(); /* Wait for next tick: */ while ((finish = GetClock()) == start) ; /* Run for 100 ticks, clamped to [0.5 sec, 5.0 sec]: */ runTime = 100.0 * (finish - start); if (runTime < 0.5) runTime = 0.5; else if (runTime > 5.0) runTime = 5.0; return runTime; } /********************************************************************** * FinishDrawing - wait for the graphics pipe to go idle * * This is needed to make sure we're not including time from some * previous uncompleted operation in our measurements. (It's not * foolproof, since we can't eliminate context switches, but we can * assume our caller has taken care of that problem.) **********************************************************************/ void FinishDrawing(void) { glFinish(); } /********************************************************************** * WaitForTick - wait for beginning of next system clock tick; return * the time **********************************************************************/ double WaitForTick(void) { double start; double current; start = GetClock(); /* Wait for next tick: */ while ((current = GetClock()) == start) ; /* Start timing: */ return current; } /********************************************************************** * InitBenchmark - measure benchmarking overhead * * This should be done once before each risky change in the * benchmarking environment. A "risky" change is one that might * reasonably be expected to affect benchmarking overhead. (For * example, changing from a direct rendering context to an indirect * rendering context.) If all measurements are being made on a single * rendering context, one call should suffice. **********************************************************************/ void InitBenchmark(void) { double runTime; long reps; double start; double finish; double current; /* Select a run time appropriate for our timer resolution: */ runTime = ChooseRunTime(); /* Wait for the pipe to clear: */ FinishDrawing(); /* Measure approximate overhead for finalization and timing * routines: */ reps = 0; start = WaitForTick(); finish = start + runTime; do { FinishDrawing(); ++reps; } while ((current = GetClock()) < finish); /* Save the overhead for use by Benchmark(): */ Overhead = (current - start) / (double) reps; } /********************************************************************** * Benchmark--measure number of caller operations performed per second * * Assumes InitBenchmark() has been called previously, to initialize * the estimate for timing overhead. **********************************************************************/ double Benchmark(void (*operation)(void)) { double runTime; long reps; long newReps; long i; double start; double current; if (!operation) return 0.0; /* Select a run time appropriate for our timer resolution: */ runTime = ChooseRunTime(); /* * Measure successively larger batches of operations until we * find one that's long enough to meet our runtime target: */ reps = 1; for (;;) { /* Run a batch: */ FinishDrawing(); start = WaitForTick(); for (i = reps; i > 0; --i) (*operation)(); FinishDrawing(); /* If we reached our target, bail out of the loop: */ current = GetClock(); if (current >= start + runTime + Overhead) break; /* * Otherwise, increase the rep count and try to reach * the target on the next attempt: */ if (current > start) newReps = reps *(0.5 + runTime / (current - start - Overhead)); else newReps = reps * 2; if (newReps == reps) reps += 1; else reps = newReps; } /* Subtract overhead and return the final operation rate: */ return (double) reps / (current - start - Overhead); } /********************************************************************** * RunTest - initialize the rendering context and run the test **********************************************************************/ void RunTest(void) { static GLfloat diffuse[] = {0.5, 0.5, 0.5, 1.0}; static GLfloat specular[] = {0.5, 0.5, 0.5, 1.0}; static GLfloat direction[] = {1.0, 1.0, 1.0, 0.0}; static GLfloat ambientMat[] = {0.1, 0.1, 0.1, 1.0}; static GLfloat specularMat[] = {0.5, 0.5, 0.5, 1.0}; if (Overhead == 0.0) InitBenchmark(); glClearColor(0.0, 0.0, 0.0, 1.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D (0, mywidth, 0, myheight); printf("%.2f frames per second\n", Benchmark(Fractal)); } /********************************************************************** * ProcessEvents - handle X11 events directed to our window * * Run the measurement each time we receive an expose event. * Exit when we receive a keypress of the Escape key. * Adjust the viewport and projection transformations when the window * changes size. **********************************************************************/ void ProcessEvents(Display* dpy) { XEvent event; Bool redraw = 0; do { char buf[31]; KeySym keysym; XNextEvent(dpy, &event); switch(event.type) { case Expose: /*redraw = 1;*/ break; case ConfigureNotify: glViewport(0, 0, WindowWidth = event.xconfigure.width, WindowHeight = event.xconfigure.height); redraw = 1; break; case KeyPress: (void) XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL); switch (keysym) { case XK_Escape: exit(EXIT_SUCCESS); default: break; } break; default: break; } } while (XPending(dpy)); if (redraw) RunTest(); } /********************************************************************** * Error - print an error message, then exit **********************************************************************/ void Error(const char* format, ...) { va_list args; fprintf(stderr, "%s: ", ApplicationName); va_start(args, format); vfprintf(stderr, format, args); va_end(args); exit(EXIT_FAILURE); } /********************************************************************** * main - create window and context, then pass control to ProcessEvents **********************************************************************/ int main(int argc, char* argv[]) { Display *dpy; XVisualInfo *vi; XSetWindowAttributes swa; Window win; GLXContext cx; ApplicationName = argv[0]; /* Get a connection: */ dpy = XOpenDisplay(NULL); if (!dpy) Error("can't open display"); /* Get an appropriate visual: */ vi = glXChooseVisual(dpy, DefaultScreen(dpy), VisualAttributes); if (!vi) Error("no suitable visual"); /* Create a GLX context: */ cx = glXCreateContext(dpy, vi, 0, GL_TRUE); /* Create a color map: */ swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone); /* Create a window: */ swa.border_pixel = 0; swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask; win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, mywidth, myheight, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa); XStoreName(dpy, win, "The fractal image"); XMapWindow(dpy, win); /* Connect the context to the window: */ glXMakeCurrent(dpy, win, cx); /* Handle events: */ while (1) ProcessEvents(dpy); } void Fractal(void){ float P, deltaP, deltaQ, X, Y, Xsquare, Ysquare; int i, j, color, row, col, response, repeat=0x30; long float elapsed, elapsed2; timespec_t start, finish; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); XMin = -2; XMax = 1.2; YMin = -1.2; YMax = 1.2; /*XMin = -.691060; XMax = -.690906; YMin = .387103; YMax = .387228; */ /*Set 5.5-------*/ /*XMin = -.691594; XMax = -.690089; YMin = .386608; YMax = .387494;*/ /*Set 7.5-------*/ /*XMin = -.749337; XMax = -.744948; YMin = .109349; YMax = .115851; */ /*Set 8--------*/ /*XMin = -.745465; XMax = -.745387; YMin = .112896; YMax = .113034; */ deltaP = (XMax - XMin)/(maxcol); deltaQ = (YMax - YMin)/(maxrow); Q[0] = YMax; /*#pragma pfor iterate(row=1; maxrow+1;1)*/ for(row = 1; row<=maxrow; row++) Q[row] = Q[row-1] - deltaQ; P = XMin; clock_gettime(CLOCK_SGI_CYCLE,&start); showtime(start); for(col=0; col255) color=255; mybuffer[row][0]=X*X; mybuffer[row][1]=Y*Y; } #pragma critical { glBegin(GL_LINES); for(j=0;j<=maxrow;j++){ glColor3ub(mybuffer[j][0], 0, mybuffer[j][1]); glVertex2f(j, col); glVertex2f(j+1, col+1); } glEnd(); P += deltaP; } } clock_gettime(CLOCK_SGI_CYCLE,&finish); showtime(finish); elapsed = finish.tv_nsec - start.tv_nsec; elapsed = elapsed/1000000000; elapsed2 = finish.tv_sec - start.tv_sec; elapsed2 = elapsed2 + elapsed; printf("elapsed time is: %lf\n",elapsed2); } void showtime(timespec_t tm) { printf("sec: %ld, ns : %ld[%g sec]\n", tm.tv_sec, tm.tv_nsec, ((double)tm.tv_sec) + ((double)tm.tv_nsec/1e9)); }