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 #undef DEBUG /* Defining this causes check_gl_error() to be called inside
25 time-critical sections, which could slow things down (since
26 it might result in a round-trip, and stall of the pipeline.)
29 extern void clear_gl_error (void);
30 extern void check_gl_error (const char *type);
32 static int fps_text_x = 10;
33 static int fps_text_y = 10;
34 static int fps_ascent, fps_descent;
35 static int fps_sample_frames = 10;
36 static GLuint font_dlist;
37 static Bool fps_clear_p = False;
40 fps_init (ModeInfo *mi)
42 const char *font = get_string_resource ("fpsFont", "Font");
47 fps_clear_p = get_boolean_resource ("fpsSolid", "FPSSolid");
49 if (!font) font = "-*-courier-bold-r-normal-*-180-*";
50 f = XLoadQueryFont(mi->dpy, font);
51 if (!f) f = XLoadQueryFont(mi->dpy, "fixed");
54 first = f->min_char_or_byte2;
55 last = f->max_char_or_byte2;
58 font_dlist = glGenLists ((GLuint) last+1);
59 check_gl_error ("glGenLists");
61 fps_ascent = f->ascent;
62 fps_descent = f->descent;
64 if (get_boolean_resource ("fpsTop", "FPSTop"))
65 fps_text_y = - (f->ascent + 10);
67 glXUseXFont(id, first, last-first+1, font_dlist + first);
68 check_gl_error ("glXUseXFont");
73 fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string)
75 /* save the current state */
76 /* note: could be expensive! */
79 y = mi->xgwa.height + y;
83 /* Sadly, this causes a stall of the graphics pipeline (as would the
84 equivalent calls to glGet*.) But there's no way around this, short
85 of having each caller set up the specific display matrix we need
86 here, which would kind of defeat the purpose of centralizing this
89 glPushAttrib(GL_TRANSFORM_BIT | /* for matrix contents */
90 GL_ENABLE_BIT | /* for various glDisable calls */
91 GL_CURRENT_BIT | /* for glColor3f() */
92 GL_LIST_BIT); /* for glListBase() */
95 check_gl_error ("glPushAttrib");
98 /* disable lighting and texturing when drawing bitmaps!
99 (glPopAttrib() restores these, I believe.)
101 glDisable(GL_TEXTURE_2D);
102 glDisable(GL_LIGHTING);
104 glDisable(GL_DEPTH_TEST);
106 /* glPopAttrib() does not restore matrix changes, so we must
107 push/pop the matrix stacks to be non-intrusive there.
109 glMatrixMode(GL_PROJECTION);
113 check_gl_error ("glPushMatrix");
117 /* Each matrix mode has its own stack, so we need to push/pop
119 glMatrixMode(GL_MODELVIEW);
123 check_gl_error ("glPushMatrix");
127 gluOrtho2D(0, mi->xgwa.width, 0, mi->xgwa.height);
129 check_gl_error ("gluOrtho2D");
132 /* clear the background */
136 glRecti (x, y - fps_descent,
138 y + fps_ascent + fps_descent);
143 glRasterPos2f (x, y);
144 glListBase (font_dlist);
145 glCallLists (strlen(string), GL_UNSIGNED_BYTE, string);
148 check_gl_error ("fps_print_string");
153 glMatrixMode(GL_PROJECTION);
157 /* clean up after our state changes */
160 check_gl_error ("glPopAttrib");
166 do_fps (ModeInfo *mi)
168 /* every N frames, get the time and use it to get the frames per second */
169 static int frame_counter = -1;
170 static double oldtime = 0; /* time in usecs, as a double */
171 static double newtime = 0;
173 static char msg [1024] = { 0, };
175 if (frame_counter == -1)
178 frame_counter = fps_sample_frames;
181 if (frame_counter++ == fps_sample_frames)
185 # ifdef GETTIMEOFDAY_TWO_ARGS
187 gettimeofday(&now, &tzp);
193 newtime = now.tv_sec + ((double) now.tv_usec * 0.000001);
195 fps = fps_sample_frames / (newtime - oldtime);
199 strcpy(msg, "FPS: (accumulating...)");
203 sprintf(msg, "FPS: %.02f", fps);
208 sprintf(buf, "%f", mi->pause / 1000000.0); /* FTSO C */
209 while(*buf && buf[strlen(buf)-1] == '0')
210 buf[strlen(buf)-1] = 0;
211 if (buf[strlen(buf)-1] == '.')
212 buf[strlen(buf)-1] = 0;
213 sprintf(msg + strlen(msg), " (including %s sec/frame delay)",
221 fps_print_string (mi, fps_text_x, fps_text_y, msg);