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)
76 /* save the current state */
77 /* note: could be expensive! */
80 y = mi->xgwa.height + y;
84 /* Sadly, this causes a stall of the graphics pipeline (as would the
85 equivalent calls to glGet*.) But there's no way around this, short
86 of having each caller set up the specific display matrix we need
87 here, which would kind of defeat the purpose of centralizing this
90 glPushAttrib(GL_TRANSFORM_BIT | /* for matrix contents */
91 GL_ENABLE_BIT | /* for various glDisable calls */
92 GL_CURRENT_BIT | /* for glColor3f() */
93 GL_LIST_BIT); /* for glListBase() */
96 check_gl_error ("glPushAttrib");
99 /* disable lighting and texturing when drawing bitmaps!
100 (glPopAttrib() restores these, I believe.)
102 glDisable(GL_TEXTURE_2D);
103 glDisable(GL_LIGHTING);
105 glDisable(GL_DEPTH_TEST);
107 /* glPopAttrib() does not restore matrix changes, so we must
108 push/pop the matrix stacks to be non-intrusive there.
110 glMatrixMode(GL_PROJECTION);
114 check_gl_error ("glPushMatrix");
118 /* Each matrix mode has its own stack, so we need to push/pop
120 glMatrixMode(GL_MODELVIEW);
124 check_gl_error ("glPushMatrix");
128 gluOrtho2D(0, mi->xgwa.width, 0, mi->xgwa.height);
130 check_gl_error ("gluOrtho2D");
133 /* clear the background */
137 glRecti (x, y - fps_descent,
139 y + fps_ascent + fps_descent);
144 glRasterPos2f (x, y);
145 glListBase (font_dlist);
146 glCallLists (strlen(string), GL_UNSIGNED_BYTE, string);
149 check_gl_error ("fps_print_string");
154 glMatrixMode(GL_PROJECTION);
158 /* clean up after our state changes */
161 check_gl_error ("glPopAttrib");
167 do_fps (ModeInfo *mi)
169 /* every N frames, get the time and use it to get the frames per second */
170 static int frame_counter = -1;
171 static double oldtime = 0; /* time in usecs, as a double */
172 static double newtime = 0;
174 static char msg [1024] = { 0, };
176 if (frame_counter == -1)
179 frame_counter = fps_sample_frames;
182 if (frame_counter++ == fps_sample_frames)
186 # ifdef GETTIMEOFDAY_TWO_ARGS
188 gettimeofday(&now, &tzp);
194 newtime = now.tv_sec + ((double) now.tv_usec * 0.000001);
196 fps = fps_sample_frames / (newtime - oldtime);
200 strcpy(msg, "FPS: (accumulating...)");
204 sprintf(msg, "FPS: %.02f", fps);
209 sprintf(buf, "%f", mi->pause / 1000000.0); /* FTSO C */
210 while(*buf && buf[strlen(buf)-1] == '0')
211 buf[strlen(buf)-1] = 0;
212 if (buf[strlen(buf)-1] == '.')
213 buf[strlen(buf)-1] = 0;
214 sprintf(msg + strlen(msg), " (including %s sec/frame delay)",
222 fps_print_string (mi, fps_text_x, fps_text_y, msg);