]> git.cworth.org Git - glfps/blob - glfps.c
Add a 32-bit target to the Makefile as well
[glfps] / glfps.c
1 #define _GNU_SOURCE /* For RTLD_NEXT */
2 #include <dlfcn.h>
3
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 #include <X11/Xlib.h>
8 #include <GL/gl.h>
9 #include <GL/glx.h>
10
11 #include <sys/time.h>
12 #include <string.h>
13
14 /* How many frames between reports. */
15 #define REPORT_FREQ 60
16
17 static void
18 on_each_frame (void)
19 {
20         static int count = 0;
21         static struct timeval tv_last;
22         struct timeval tv_now;
23
24         if ((count % REPORT_FREQ) == 0) {
25                 gettimeofday (&tv_now, NULL);
26                 if (count == 0) {
27                         printf ("glfps: Initializing FPS timer\n");
28                 } else {
29                         double elapsed = ((tv_now.tv_sec - tv_last.tv_sec) +
30                                           (tv_now.tv_usec - tv_last.tv_usec) / 1e6);
31                         printf ("FPS: %.3f\n", ((double) REPORT_FREQ) / elapsed);
32                 }
33                 tv_last = tv_now;
34         }
35
36         count++;
37 }
38
39 static void *do_real_dlsym (void *handle, const char *symbol);
40
41 static typeof(&glXSwapBuffers) real_glXSwapBuffers;
42
43 void
44 glXSwapBuffers (Display *dpy, GLXDrawable drawable)
45 {
46         if (real_glXSwapBuffers == NULL)
47                 real_glXSwapBuffers = do_real_dlsym (RTLD_NEXT, "glXSwapBuffers");
48
49         on_each_frame ();
50
51         real_glXSwapBuffers (dpy, drawable);
52 }
53
54 static typeof(&glXGetProcAddressARB) real_glXGetProcAddressARB;
55
56 void
57 (*glXGetProcAddressARB (const GLubyte *func))(void)
58 {
59         if (strcmp((char *) func, "glXSwapBuffers") == 0)
60                 return (void*) glXSwapBuffers;
61
62         if (real_glXGetProcAddressARB == NULL)
63                 real_glXGetProcAddressARB = do_real_dlsym (RTLD_NEXT, "glXGetProcAddressARB");
64
65         return real_glXGetProcAddressARB (func);
66 }
67
68 static typeof(&glXGetProcAddress) real_glXGetProcAddress;
69
70 void
71 (*glXGetProcAddress (const GLubyte *func))(void)
72 {
73         if (strcmp((char *) func, "glXSwapBuffers") == 0)
74                 return (void*) glXSwapBuffers;
75
76         if (real_glXGetProcAddress == NULL)
77                 real_glXGetProcAddress = do_real_dlsym (RTLD_NEXT, "glXGetProcAddress");
78
79         return real_glXGetProcAddress (func);
80 }
81
82 /* We rely on an internal symbol within glibc in order to be able to
83  * get a handle on the real dlsym function, (we can't call dlsym to
84  * find the address of dlsym itself of course). */
85 void * __libc_dlsym(void *, const char *);
86
87 static void *
88 do_real_dlsym (void *handle, const char *symbol)
89 {
90         static typeof(&dlsym) real_dlsym = NULL;
91
92         if (real_dlsym == NULL) {
93                 void *libdl_handle = dlopen ("libdl.so.2", RTLD_LAZY);
94                 real_dlsym = __libc_dlsym(libdl_handle, "dlsym");
95         }
96
97         return real_dlsym (handle, symbol);
98 }
99
100 void *
101 dlsym (void *handle, const char *symbol)
102 {
103         void *ret;
104
105         ret = do_real_dlsym (handle, symbol);
106
107         if (strcmp (symbol, "glXSwapBuffers") == 0) {
108                 real_glXSwapBuffers = ret;
109                 return &glXSwapBuffers;
110         }
111
112         if (strcmp (symbol, "glXGetProcAddressARB") == 0) {
113                 real_glXGetProcAddressARB = ret;
114                 return &glXGetProcAddressARB;
115         }
116
117         if (strcmp (symbol, "glXGetProcAddress") == 0) {
118                 real_glXGetProcAddress = ret;
119                 return &glXGetProcAddress;
120         }
121
122         return ret;
123 }