Skip to content

Instantly share code, notes, and snippets.

@tpruzina
Last active June 11, 2022 00:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tpruzina/a610c95807b61b3ccb6eae00f91fa6d8 to your computer and use it in GitHub Desktop.
Save tpruzina/a610c95807b61b3ccb6eae00f91fa6d8 to your computer and use it in GitHub Desktop.
#include <dlfcn.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GL/glx.h"
// compile: "gcc frame_counter.c -ldl -D_GNU_SOURCE -shared -fPIC -o frame_counter.so"
// run: LD_PRELOAD=./frame_counter.so glxgears
void (*_glXSwapBuffers)(Display *dpy, GLXDrawable drawable);
struct timespec then,now;
static unsigned frame_counter, accumulator, interval;
FILE *fd;
char name[128] = {0};
__attribute__((constructor))
void foo(void)
{
clock_gettime(CLOCK_REALTIME,&then);
char *executable_path = getenv("_");
char *base_name = executable_path;
while(*++executable_path)
{
if(*executable_path == '/')
{
base_name = executable_path+1;
}
}
strncpy(name, base_name, 120);
int len = strlen(base_name);
strcpy((char*)(name+len), ".output");
fd = fopen(name, "w");
if(!fd)
{
fprintf(stderr, "FML, I cant write to %s\n", name);
exit(1);
}
else
printf("Saving FPS measurements into %s\n", name);
}
__attribute__((destructor))
void foo2(void)
{
fprintf(fd, "%d\n", accumulator / (interval ? interval : 1));
fclose(fd);
}
void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
{
_glXSwapBuffers = (typeof(_glXSwapBuffers)) dlsym(RTLD_NEXT, "glXSwapBuffers");
_glXSwapBuffers(dpy, drawable);
clock_gettime(CLOCK_REALTIME,&now);
frame_counter++;
long diff = ( now.tv_nsec - then.tv_nsec ) + ( now.tv_sec - then.tv_sec ) * 1E9;
// one sec passed between then and current time?
if(diff >= 1E9)
{
then = now;
fprintf(fd, "%d\n", frame_counter);
accumulator += frame_counter;
interval++;
frame_counter = 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment