http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / glx / fps.c
index b254397eab2381c0a82a1996512e2b997d880334..237ef1fef6daf9bab1a6d5d79e6e9af977727e7d 100644 (file)
@@ -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,14 +72,18 @@ fps_init (ModeInfo *mi)
 static void
 fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string)
 {
-  int i;
-  /* 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
@@ -133,17 +137,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");
@@ -163,26 +179,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);
@@ -190,34 +209,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.) */
 }