X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Ffps.c;h=9d50cad5213e8d25785e2abab5886db5ffa6064c;hb=2d04c4f22466851aedb6ed0f2919d148f726b889;hp=16ee1b0827fb7b852eaf8ab6a60c1f0ef1a7cba4;hpb=8eb2873d7054e705c4e83f22d18c40946a9e2529;p=xscreensaver diff --git a/hacks/glx/fps.c b/hacks/glx/fps.c index 16ee1b08..9d50cad5 100644 --- a/hacks/glx/fps.c +++ b/hacks/glx/fps.c @@ -32,9 +32,9 @@ extern void check_gl_error (const char *type); static int fps_text_x = 10; static int fps_text_y = 10; static int fps_ascent, fps_descent; -static int fps_sample_frames = 10; static GLuint font_dlist; static Bool fps_clear_p = False; +static char fps_string[1024]; static void fps_init (ModeInfo *mi) @@ -72,13 +72,18 @@ fps_init (ModeInfo *mi) static void fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string) { - /* save the current state */ - /* note: could be expensive! */ + const char *L2 = strchr (string, '\n'); if (y < 0) - y = mi->xgwa.height + y; + { + y = mi->xgwa.height + y; + if (L2) + y -= (fps_ascent + fps_descent); + } +# ifdef DEBUG clear_gl_error (); +# endif /* Sadly, this causes a stall of the graphics pipeline (as would the equivalent calls to glGet*.) But there's no way around this, short @@ -86,22 +91,23 @@ fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string) here, which would kind of defeat the purpose of centralizing this code in one file. */ - glPushAttrib(GL_TRANSFORM_BIT | /* for matrix contents */ - GL_ENABLE_BIT | /* for various glDisable calls */ - GL_CURRENT_BIT | /* for glColor3f() */ - GL_LIST_BIT); /* for glListBase() */ + glPushAttrib (GL_TRANSFORM_BIT | /* for matrix contents */ + GL_ENABLE_BIT | /* for various glDisable calls */ + GL_CURRENT_BIT | /* for glColor3f() */ + GL_LIST_BIT); /* for glListBase() */ { # ifdef DEBUG check_gl_error ("glPushAttrib"); # endif /* disable lighting and texturing when drawing bitmaps! - (glPopAttrib() restores these, I believe.) + (glPopAttrib() restores these.) */ - glDisable(GL_TEXTURE_2D); - glDisable(GL_LIGHTING); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); + glDisable (GL_TEXTURE_2D); + glDisable (GL_LIGHTING); + glDisable (GL_BLEND); + glDisable (GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); /* glPopAttrib() does not restore matrix changes, so we must push/pop the matrix stacks to be non-intrusive there. @@ -132,17 +138,29 @@ fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string) /* clear the background */ if (fps_clear_p) { + int lines = L2 ? 2 : 1; glColor3f (0, 0, 0); - glRecti (x, y - fps_descent, + glRecti (x / 2, y - fps_descent, mi->xgwa.width - x, - y + fps_ascent + fps_descent); + y + lines * (fps_ascent + fps_descent)); } /* draw the text */ glColor3f (1, 1, 1); glRasterPos2f (x, y); glListBase (font_dlist); - glCallLists (strlen(string), GL_UNSIGNED_BYTE, string); + + if (L2) + { + L2++; + glCallLists (strlen(L2), GL_UNSIGNED_BYTE, L2); + glRasterPos2f (x, y + (fps_ascent + fps_descent)); + glCallLists (L2 - string - 1, GL_UNSIGNED_BYTE, string); + } + else + { + glCallLists (strlen(string), GL_UNSIGNED_BYTE, string); + } # ifdef DEBUG check_gl_error ("fps_print_string"); @@ -162,26 +180,29 @@ fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string) } -void -do_fps (ModeInfo *mi) +GLfloat +fps_1 (ModeInfo *mi) { - /* every N frames, get the time and use it to get the frames per second */ - static int frame_counter = -1; - static double oldtime = 0; /* time in usecs, as a double */ - static double newtime = 0; - - static char msg [1024] = { 0, }; - - if (frame_counter == -1) + static Bool initted_p = False; + static int last_ifps = -1; + static GLfloat last_fps = -1; + static int frame_count = 0; + static struct timeval prev = { 0, 0 }; + static struct timeval now = { 0, 0 }; + + if (!initted_p) { + initted_p = True; fps_init (mi); - frame_counter = fps_sample_frames; + strcpy (fps_string, "FPS: (accumulating...)"); } - if (frame_counter++ == fps_sample_frames) + /* Every N frames (where N is approximately one second's worth of frames) + check the wall clock. We do this because checking the wall clock is + a slow operation. + */ + if (frame_count++ >= last_ifps) { - double fps; - struct timeval now; # ifdef GETTIMEOFDAY_TWO_ARGS struct timezone tzp; gettimeofday(&now, &tzp); @@ -189,34 +210,72 @@ do_fps (ModeInfo *mi) gettimeofday(&now); # endif - oldtime = newtime; - newtime = now.tv_sec + ((double) now.tv_usec * 0.000001); + if (prev.tv_sec == 0) + prev = now; + } - fps = fps_sample_frames / (newtime - oldtime); + /* If we've probed the wall-clock time, regenerate the string. + */ + if (now.tv_sec != prev.tv_sec) + { + double uprev = prev.tv_sec + ((double) prev.tv_usec * 0.000001); + double unow = now.tv_sec + ((double) now.tv_usec * 0.000001); + double fps = frame_count / (unow - uprev); - if (fps < 0.0001) + prev = now; + frame_count = 0; + last_ifps = fps; + last_fps = fps; + + sprintf (fps_string, "FPS: %.02f", fps); + + if (mi->pause != 0) { - strcpy(msg, "FPS: (accumulating...)"); + char buf[40]; + sprintf(buf, "%f", mi->pause / 1000000.0); /* FTSO C */ + while(*buf && buf[strlen(buf)-1] == '0') + buf[strlen(buf)-1] = 0; + if (buf[strlen(buf)-1] == '.') + buf[strlen(buf)-1] = 0; + sprintf(fps_string + strlen(fps_string), + " (including %s sec/frame delay)", + buf); } - else + + if (mi->polygon_count > 0) { - sprintf(msg, "FPS: %.02f", fps); - - if (mi->pause != 0) - { - char buf[40]; - sprintf(buf, "%f", mi->pause / 1000000.0); /* FTSO C */ - while(*buf && buf[strlen(buf)-1] == '0') - buf[strlen(buf)-1] = 0; - if (buf[strlen(buf)-1] == '.') - buf[strlen(buf)-1] = 0; - sprintf(msg + strlen(msg), " (including %s sec/frame delay)", - buf); - } - } + unsigned long p = mi->polygon_count; + const char *s = ""; +# if 0 + if (p >= (1024 * 1024)) p >>= 20, s = "M"; + else if (p >= 2048) p >>= 10, s = "K"; +# endif - frame_counter = 0; + strcat (fps_string, "\nPolys: "); + if (p >= 1000000) + sprintf (fps_string + strlen(fps_string), "%lu,%03lu,%03lu%s", + (p / 1000000), ((p / 1000) % 1000), (p % 1000), s); + else if (p >= 1000) + sprintf (fps_string + strlen(fps_string), "%lu,%03lu%s", + (p / 1000), (p % 1000), s); + else + sprintf (fps_string + strlen(fps_string), "%lu%s", p, s); + } } - fps_print_string (mi, fps_text_x, fps_text_y, msg); + return last_fps; +} + +void +fps_2 (ModeInfo *mi) +{ + fps_print_string (mi, fps_text_x, fps_text_y, fps_string); +} + + +void +do_fps (ModeInfo *mi) +{ + fps_1 (mi); /* Lazily compute current FPS value, about once a second. */ + fps_2 (mi); /* Print the string every frame (else nothing shows up.) */ }