1 /* tube, Copyright (c) 2001 Jamie Zawinski <jwz@jwz.org>
2 * Utility function to draw a frames-per-second display.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
17 #include "screenhack.h"
18 #include "xlockmoreI.h"
24 extern void clear_gl_error (void);
25 extern void check_gl_error (const char *type);
27 static int fps_text_x = 10;
28 static int fps_text_y = 10;
29 static int fps_ascent, fps_descent;
30 static int fps_sample_frames = 10;
31 static GLuint font_dlist;
32 static Bool fps_clear_p = False;
35 fps_init (ModeInfo *mi)
37 const char *font = get_string_resource ("fpsFont", "Font");
42 fps_clear_p = get_boolean_resource ("fpsSolid", "FPSSolid");
44 if (!font) font = "-*-courier-bold-r-normal-*-180-*";
45 f = XLoadQueryFont(mi->dpy, font);
46 if (!f) f = XLoadQueryFont(mi->dpy, "fixed");
49 first = f->min_char_or_byte2;
50 last = f->max_char_or_byte2;
53 font_dlist = glGenLists ((GLuint) last+1);
54 check_gl_error ("glGenLists");
56 fps_ascent = f->ascent;
57 fps_descent = f->descent;
59 if (get_boolean_resource ("fpsTop", "FPSTop"))
60 fps_text_y = - (f->ascent + 10);
62 glXUseXFont(id, first, last-first+1, font_dlist + first);
63 check_gl_error ("glXUseXFont");
68 fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string)
71 /* save the current state */
72 /* note: could be expensive! */
75 y = mi->xgwa.height + y;
78 glPushAttrib(GL_ALL_ATTRIB_BITS);
80 check_gl_error ("glPushAttrib");
82 /* disable lighting and texturing when drawing bitmaps!
83 (glPopAttrib() restores these, I believe.)
85 glDisable(GL_TEXTURE_2D);
86 glDisable(GL_LIGHTING);
88 glDisable(GL_DEPTH_TEST);
90 /* glPopAttrib() does not restore matrix changes, so we must
91 push/pop the matrix stacks to be non-intrusive there.
93 glMatrixMode(GL_PROJECTION);
96 check_gl_error ("glPushMatrix");
99 /* Each matrix mode has its own stack, so we need to push/pop
101 glMatrixMode(GL_MODELVIEW);
104 check_gl_error ("glPushMatrix");
107 gluOrtho2D(0, mi->xgwa.width, 0, mi->xgwa.height);
108 check_gl_error ("gluOrtho2D");
110 /* clear the background */
114 glRecti (x, y - fps_descent,
116 y + fps_ascent + fps_descent);
121 glRasterPos2f (x, y);
122 for (i = 0; i < strlen(string); i++)
123 glCallList (font_dlist + (int)string[i]);
125 check_gl_error ("fps_print_string");
129 glMatrixMode(GL_PROJECTION);
133 /* clean up after our state changes */
135 check_gl_error ("glPopAttrib");
140 do_fps (ModeInfo *mi)
142 /* every N frames, get the time and use it to get the frames per second */
143 static int frame_counter = -1;
144 static double oldtime = 0; /* time in usecs, as a double */
145 static double newtime = 0;
147 static char msg [1024] = { 0, };
149 if (frame_counter == -1)
152 frame_counter = fps_sample_frames;
155 if (frame_counter++ == fps_sample_frames)
159 # ifdef GETTIMEOFDAY_TWO_ARGS
161 gettimeofday(&now, &tzp);
167 newtime = now.tv_sec + ((double) now.tv_usec * 0.000001);
169 fps = fps_sample_frames / (newtime - oldtime);
173 strcpy(msg, "FPS: (accumulating...)");
177 sprintf(msg, "FPS: %.02f", fps);
182 sprintf(buf, "%f", mi->pause / 1000000.0); /* FTSO C */
183 while(*buf && buf[strlen(buf)-1] == '0')
184 buf[strlen(buf)-1] = 0;
185 if (buf[strlen(buf)-1] == '.')
186 buf[strlen(buf)-1] = 0;
187 sprintf(msg + strlen(msg), " (including %s sec/frame delay)",
195 fps_print_string (mi, fps_text_x, fps_text_y, msg);