Skip to content

Instantly share code, notes, and snippets.

@shuhaowu
Forked from Cloudef/glvsync.c
Created June 24, 2020 03:00
Show Gist options
  • Save shuhaowu/878ebe2f4a2a7ee06d2d530627ccbdc1 to your computer and use it in GitHub Desktop.
Save shuhaowu/878ebe2f4a2a7ee06d2d530627ccbdc1 to your computer and use it in GitHub Desktop.

Revisions

  1. @Cloudef Cloudef revised this gist Dec 2, 2016. 1 changed file with 39 additions and 4 deletions.
    43 changes: 39 additions & 4 deletions glvsync.c
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,7 @@
    * gcc -m32 -std=c99 -fPIC -shared -Wl,-soname,glvsync.so glvsync.c -o glvsync.so (for 32bit)
    *
    * Force VSYNC interval on OpenGL applications
    * Alternatively can also try FPS locking a OpenGL program
    * Usage: LD_PRELOAD="/path/to/glvsync.so" ./program
    */

    @@ -12,10 +13,17 @@
    #include <string.h>
    #include <stdio.h>
    #include <stdbool.h>
    #include <stdint.h>
    #include <unistd.h>
    #include <sched.h>
    #include <time.h>
    #include <err.h>

    static uint32_t LOCK_FPS = 0; // Tries to lock swaps to FPS, 0 to disable (default) (override with _GLVSYNC_FPS)
    // If using fps locking, it may be good idea to disable vsync

    static int SYNC_INTERVAL = 1; // 60 FPS @ 60Hz (override with _GLVSYNC_INTERVAL env variable)
    // e.g. 2 would be 30 FPS @ 60Hz
    // e.g. 2 would be 30 FPS @ 60Hz, 0 to force disable vsync

    extern void *_dl_sym(void*, const char*, void*);

    @@ -34,11 +42,20 @@ static void* store_real_symbol_and_return_fake_symbol(const char *symbol, void *
    #define SET_IF_NOT_HOOKED(x, y) if (!x) { x = y; warnx("glvsync: SET %s", #x); }
    #define WARN_ONCE(x, ...) do { static bool o = false; if (!o) { warnx(x, ##__VA_ARGS__); o = true; } } while (0)

    static uint32_t get_lock_fps(void)
    {
    static const char *val;
    if (!val && (val = getenv("_GLVSYNC_FPS")))
    LOCK_FPS = strtol(val, NULL, 10);

    return LOCK_FPS;
    }

    static int get_interval(void)
    {
    static const char *swap;
    if (!swap && (swap = getenv("_GLVSYNC_INTERVAL")))
    SYNC_INTERVAL = strtol(swap, NULL, 10);
    static const char *val;
    if (!val && (val = getenv("_GLVSYNC_INTERVAL")))
    SYNC_INTERVAL = strtol(val, NULL, 10);

    return SYNC_INTERVAL;
    }
    @@ -85,6 +102,13 @@ __GLXextFuncPtr glXGetProcAddress(const GLubyte *procname)
    return (_glXGetProcAddress ? store_real_symbol_and_return_fake_symbol(procname, _glXGetProcAddress(procname)) : NULL);
    }

    static uint64_t get_time_ns(void)
    {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return (uint64_t)ts.tv_sec * (uint64_t)1e9 + (uint64_t)ts.tv_nsec;
    }

    void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
    {
    HOOK(_glXSwapBuffers);
    @@ -101,6 +125,17 @@ void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
    }

    _glXSwapBuffers(dpy, drawable);

    if (get_lock_fps() > 0) {
    static uint64_t last_time;
    const double interval = 1e9 / get_lock_fps();
    const useconds_t step = interval / 1e6;
    while (last_time > 0 && get_time_ns() - last_time < interval) {
    sched_yield();
    usleep(step);
    }
    last_time = get_time_ns();
    }
    }

    void* store_real_symbol_and_return_fake_symbol(const char *symbol, void *ret)
  2. @Cloudef Cloudef revised this gist Dec 2, 2016. 1 changed file with 75 additions and 84 deletions.
    159 changes: 75 additions & 84 deletions glvsync.c
    Original file line number Diff line number Diff line change
    @@ -11,144 +11,135 @@
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdbool.h>
    #include <err.h>

    static int SYNC_INTERVAL = 2; // 30 FPS @ 60hz (override with _GLVSYNC_INTERVAL env variable)
    static int SYNC_INTERVAL = 1; // 60 FPS @ 60Hz (override with _GLVSYNC_INTERVAL env variable)
    // e.g. 2 would be 30 FPS @ 60Hz

    extern void *_dl_sym(void*, const char*, void*);

    static void* (*_dlsym)(void*, const char*) = NULL;
    static int (*_glXSwapIntervalEXT)(Display*, GLXDrawable, int interval) = NULL;
    static int (*_glXSwapIntervalSGI)(unsigned int interval) = NULL;
    static int (*_glXSwapIntervalMESA)(unsigned int interval) = NULL;
    static void (*_glXSwapBuffers)(Display*, GLXDrawable) = NULL;
    static void* (*_glXGetProcAddress)(const GLubyte*) = NULL;
    static void* (*_glXGetProcAddressARB)(const GLubyte*) = NULL;
    static void* (*_glXGetProcAddressEXT)(const GLubyte*) = NULL;
    static void* store_real_symbol_and_return_fake_symbol(const char *symbol, void *ret);

    #define HOOK_DLSYM(x, y) if (!x) { if ((x = _dl_sym(RTLD_NEXT, __func__, y))) warnx("glvsync: HOOK dlsym"); }
    #define HOOK(x) if (!x) if ((x = _dlsym(RTLD_NEXT, __func__))) { warnx("glvsync: HOOK %s", __func__); }
    #define SET_IF_NOT_HOOKED(x, y) if (!x) { x = y; warnx("glvsync: SET %s", #x); }
    #define WARN_ONCE(x, ...) do { static bool o = false; if (!o) { warnx(x, ##__VA_ARGS__); o = true; } } while (0)

    static int get_interval(void)
    {
    static const char *swap;
    if (!swap && (swap = getenv("_GLVSYNC_INTERVAL")))
    SYNC_INTERVAL = strtol(swap, NULL, 10);

    return SYNC_INTERVAL;
    }

    int glXSwapIntervalEXT(Display *dpy, GLXDrawable drawable, int interval)
    {
    (void)interval;
    if (!_glXSwapIntervalEXT) _glXSwapIntervalEXT = _dl_sym(RTLD_NEXT, __FUNCTION__, glXSwapIntervalEXT);
    return _glXSwapIntervalEXT(dpy, drawable, SYNC_INTERVAL);
    HOOK(_glXSwapIntervalEXT);
    if (_glXSwapIntervalEXT) WARN_ONCE("glvsync: FORCE SWAP (EXT)");
    return (_glXSwapIntervalEXT ? _glXSwapIntervalEXT(dpy, drawable, get_interval()) : 0);
    }

    int glXSwapIntervalSGI(unsigned int interval)
    {
    (void)interval;
    if (!_glXSwapIntervalSGI) _glXSwapIntervalSGI = _dl_sym(RTLD_NEXT, __FUNCTION__, glXSwapIntervalSGI);
    return _glXSwapIntervalSGI(SYNC_INTERVAL);
    HOOK(_glXSwapIntervalSGI);
    if (_glXSwapIntervalSGI) WARN_ONCE("glvsync: FORCE SWAP (SGI)");
    return (_glXSwapIntervalSGI ? _glXSwapIntervalSGI(get_interval()) : 0);
    }

    int glXSwapIntervalMESA(unsigned int interval)
    {
    (void)interval;
    if (!_glXSwapIntervalMESA) _glXSwapIntervalMESA = _dl_sym(RTLD_NEXT, __FUNCTION__, glXSwapIntervalMESA);
    return _glXSwapIntervalMESA(SYNC_INTERVAL);
    }

    static __GLXextFuncPtr hookedProc(const GLubyte *procname, __GLXextFuncPtr ret)
    {
    if (!strcmp((const char*)procname, "glXSwapIntervalEXT")) {
    printf("--- HOOK GLXSWAPINTERVALEXT\n");
    _glXSwapIntervalEXT = (void*)ret;
    return (__GLXextFuncPtr)_glXSwapIntervalEXT;
    } else if (!strcmp((const char*)procname, "glXSwapIntervalSGI")) {
    printf("--- HOOK GLXSWAPINTERVALSGI\n");
    _glXSwapIntervalSGI = (void*)ret;
    return (__GLXextFuncPtr)glXSwapIntervalSGI;
    } else if (!strcmp((const char*)procname, "glXSwapIntervalMESA")) {
    printf("--- HOOK GLXSWAPINTERVALMESA\n");
    _glXSwapIntervalMESA = (void*)ret;
    return (__GLXextFuncPtr)glXSwapIntervalMESA;
    }
    return ret;
    HOOK(_glXSwapIntervalMESA);
    if (_glXSwapIntervalMESA) WARN_ONCE("glvsync: FORCE SWAP (MESA)");
    return (_glXSwapIntervalMESA ? _glXSwapIntervalMESA(get_interval()) : 0);
    }

    __GLXextFuncPtr glXGetProcAddressEXT(const GLubyte *procname)
    {
    __GLXextFuncPtr ret = NULL;
    if (!_glXGetProcAddressEXT) _glXGetProcAddressEXT = _dl_sym(RTLD_NEXT, __FUNCTION__, glXGetProcAddressEXT);
    if (!(ret = _glXGetProcAddressEXT(procname))) return ret;
    return hookedProc(procname, ret);
    HOOK(_glXGetProcAddressEXT);
    return (_glXGetProcAddressEXT ? store_real_symbol_and_return_fake_symbol(procname, _glXGetProcAddressEXT(procname)) : NULL);
    }

    __GLXextFuncPtr glXGetProcAddressARB(const GLubyte *procname)
    {
    __GLXextFuncPtr ret = NULL;
    if (!_glXGetProcAddressARB) _glXGetProcAddressARB = _dl_sym(RTLD_NEXT, __FUNCTION__, glXGetProcAddressARB);
    if (!(ret = _glXGetProcAddressARB(procname))) return ret;
    return hookedProc(procname, ret);
    HOOK(_glXGetProcAddressARB);
    return (_glXGetProcAddressARB ? store_real_symbol_and_return_fake_symbol(procname, _glXGetProcAddressARB(procname)) : NULL);
    }

    __GLXextFuncPtr glXGetProcAddress(const GLubyte *procname)
    {
    __GLXextFuncPtr ret = NULL;
    if (!_glXGetProcAddress) _glXGetProcAddress = _dl_sym(RTLD_NEXT, __FUNCTION__, glXGetProcAddress);
    if (!(ret = _glXGetProcAddress(procname))) return ret;
    return hookedProc(procname, ret);
    HOOK(_glXGetProcAddress);
    return (_glXGetProcAddress ? store_real_symbol_and_return_fake_symbol(procname, _glXGetProcAddress(procname)) : NULL);
    }

    void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
    {
    static int once = 0;
    static int counter = 0;
    if (!_glXSwapBuffers) _glXSwapBuffers = _dl_sym(RTLD_NEXT, __FUNCTION__, glXSwapBuffers);

    if (!once) {
    const char *swap = getenv("_GLVSYNC_INTERVAL");
    if (swap) SYNC_INTERVAL = strtol(swap, NULL, 10);
    }

    if (_glXSwapIntervalEXT) {
    if (!once) printf("--- FORCE SWAP (EXT)\n");
    _glXSwapIntervalEXT(dpy, drawable, SYNC_INTERVAL);
    } else if (_glXSwapIntervalSGI) {
    if (!once) printf("--- FORCE SWAP (SGI)\n");
    _glXSwapIntervalSGI(SYNC_INTERVAL);
    } else if (_glXSwapIntervalMESA) {
    if (!once) printf("--- FORCE SWAP (MESA)\n");
    _glXSwapIntervalMESA(SYNC_INTERVAL);
    HOOK(_glXSwapBuffers);

    {
    static bool once = false;
    if (!once) {
    warnx("glvsync: INITIAL SWAP");
    glXSwapIntervalEXT(dpy, drawable, 0);
    glXSwapIntervalSGI(0);
    glXSwapIntervalMESA(0);
    once = true;
    }
    }

    _glXSwapBuffers(dpy, drawable);
    once = 1;
    }

    void *dlsym(void *handle, const char *symbol)
    void* store_real_symbol_and_return_fake_symbol(const char *symbol, void *ret)
    {
    void *ret = NULL;
    if (symbol && !strcmp(symbol, "dlsym")) return dlsym;
    if (!(ret = _dl_sym(handle, symbol, dlsym))) return ret;
    if (!ret || !symbol)
    return ret;

    if (!strcmp(symbol, "glXGetProcAddressARB")) {
    printf("--- HOOK GLXGETPROCADDRESSARB\n");
    _glXGetProcAddressARB = ret;
    if (!strcmp(symbol, "glXSwapIntervalEXT")) {
    SET_IF_NOT_HOOKED(_glXSwapIntervalEXT, ret);
    return glXSwapIntervalEXT;
    } else if (!strcmp(symbol, "glXSwapIntervalSGI")) {
    SET_IF_NOT_HOOKED(_glXSwapIntervalSGI, ret);
    return glXSwapIntervalSGI;
    } else if (!strcmp(symbol, "glXSwapIntervalMESA")) {
    SET_IF_NOT_HOOKED(_glXSwapIntervalMESA, ret);
    return glXSwapIntervalMESA;
    } else if (!strcmp(symbol, "glXGetProcAddressEXT")) {
    SET_IF_NOT_HOOKED(_glXGetProcAddressEXT, ret);
    return glXGetProcAddressEXT;
    } else if (!strcmp(symbol, "glXGetProcAddressARB")) {
    SET_IF_NOT_HOOKED(_glXGetProcAddressARB, ret);
    return glXGetProcAddressARB;
    } else if (!strcmp(symbol, "glXGetProcAddress")) {
    printf("--- HOOK GLXGETPROCADDRESS\n");
    _glXGetProcAddress = ret;
    SET_IF_NOT_HOOKED(_glXGetProcAddress, ret);
    return glXGetProcAddress;
    } else if (!strcmp(symbol, "glXGetProcAddressEXT")) {
    printf("--- HOOK GLXGETPROCADDRESSEXT\n");
    _glXGetProcAddressEXT = ret;
    return glXGetProcAddressEXT;
    } else if (!strcmp(symbol, "glXSwapBuffers")) {
    printf("--- HOOK GLXSWAPBUFFERS\n");
    _glXSwapBuffers = ret;
    SET_IF_NOT_HOOKED(_glXSwapBuffers, ret);
    return glXSwapBuffers;
    } else if (!strcmp(symbol, "glXSwapIntervalEXT")) {
    printf("--- HOOK GLXSWAPINTERVALEXT\n");
    _glXSwapIntervalEXT = ret;
    return _glXSwapIntervalEXT;
    } else if (!strcmp(symbol, "glXSwapIntervalSGI")) {
    printf("--- HOOK GLXSWAPINTERVALSGI\n");
    _glXSwapIntervalSGI = ret;
    return _glXSwapIntervalSGI;
    } else if (!strcmp(symbol, "glXSwapIntervalMESA")) {
    printf("--- HOOK GLXSWAPINTERVALMESA\n");
    _glXSwapIntervalMESA = ret;
    return _glXSwapIntervalMESA;
    }

    return ret;
    }

    /* vim: set ts=8 sw=3 tw=0 :*/
    void* dlsym(void *handle, const char *symbol)
    {
    HOOK_DLSYM(_dlsym, dlsym);

    if (symbol && !strcmp(symbol, "dlsym"))
    return dlsym;

    return store_real_symbol_and_return_fake_symbol(symbol, _dlsym(handle, symbol));
    }
  3. @Cloudef Cloudef revised this gist Feb 28, 2014. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion glvsync.c
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    /* gcc -std=c99 -fPIC -shared -Wl,-soname,glvsync.so glvsync.c -o glvsync.so
    * gcc -m32 -std=c99 -fPIC -shared -Wl,-soname,glvsync.so glvsync.c -o glvsync.so (for 32bit)
    *
    * Force VSYNC interval on OpenGL applications
    * Usage: LD_PRELOAD="/path/to/glvsync.so" ./program
    @@ -90,7 +91,7 @@ void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
    {
    static int once = 0;
    static int counter = 0;
    if (!_glXSwapBuffers) _glXSwapBuffers = _dl_sym(RTLD_NEXT, __FUNCTION__ ,glXSwapBuffers);
    if (!_glXSwapBuffers) _glXSwapBuffers = _dl_sym(RTLD_NEXT, __FUNCTION__, glXSwapBuffers);

    if (!once) {
    const char *swap = getenv("_GLVSYNC_INTERVAL");
  4. @Cloudef Cloudef revised this gist Feb 28, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion glvsync.c
    Original file line number Diff line number Diff line change
    @@ -11,7 +11,7 @@
    #include <string.h>
    #include <stdio.h>

    static int SYNC_INTERVAL = 2; // 30 FPS (override with _GLVSYNC_INTERVAL env variable)
    static int SYNC_INTERVAL = 2; // 30 FPS @ 60hz (override with _GLVSYNC_INTERVAL env variable)

    extern void *_dl_sym(void*, const char*, void*);

  5. @Cloudef Cloudef created this gist Feb 19, 2014.
    153 changes: 153 additions & 0 deletions glvsync.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,153 @@
    /* gcc -std=c99 -fPIC -shared -Wl,-soname,glvsync.so glvsync.c -o glvsync.so
    *
    * Force VSYNC interval on OpenGL applications
    * Usage: LD_PRELOAD="/path/to/glvsync.so" ./program
    */

    #define _GNU_SOURCE
    #include <dlfcn.h>
    #include <GL/glx.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>

    static int SYNC_INTERVAL = 2; // 30 FPS (override with _GLVSYNC_INTERVAL env variable)

    extern void *_dl_sym(void*, const char*, void*);

    static int (*_glXSwapIntervalEXT)(Display*, GLXDrawable, int interval) = NULL;
    static int (*_glXSwapIntervalSGI)(unsigned int interval) = NULL;
    static int (*_glXSwapIntervalMESA)(unsigned int interval) = NULL;
    static void (*_glXSwapBuffers)(Display*, GLXDrawable) = NULL;
    static void* (*_glXGetProcAddress)(const GLubyte*) = NULL;
    static void* (*_glXGetProcAddressARB)(const GLubyte*) = NULL;
    static void* (*_glXGetProcAddressEXT)(const GLubyte*) = NULL;

    int glXSwapIntervalEXT(Display *dpy, GLXDrawable drawable, int interval)
    {
    (void)interval;
    if (!_glXSwapIntervalEXT) _glXSwapIntervalEXT = _dl_sym(RTLD_NEXT, __FUNCTION__, glXSwapIntervalEXT);
    return _glXSwapIntervalEXT(dpy, drawable, SYNC_INTERVAL);
    }

    int glXSwapIntervalSGI(unsigned int interval)
    {
    (void)interval;
    if (!_glXSwapIntervalSGI) _glXSwapIntervalSGI = _dl_sym(RTLD_NEXT, __FUNCTION__, glXSwapIntervalSGI);
    return _glXSwapIntervalSGI(SYNC_INTERVAL);
    }

    int glXSwapIntervalMESA(unsigned int interval)
    {
    (void)interval;
    if (!_glXSwapIntervalMESA) _glXSwapIntervalMESA = _dl_sym(RTLD_NEXT, __FUNCTION__, glXSwapIntervalMESA);
    return _glXSwapIntervalMESA(SYNC_INTERVAL);
    }

    static __GLXextFuncPtr hookedProc(const GLubyte *procname, __GLXextFuncPtr ret)
    {
    if (!strcmp((const char*)procname, "glXSwapIntervalEXT")) {
    printf("--- HOOK GLXSWAPINTERVALEXT\n");
    _glXSwapIntervalEXT = (void*)ret;
    return (__GLXextFuncPtr)_glXSwapIntervalEXT;
    } else if (!strcmp((const char*)procname, "glXSwapIntervalSGI")) {
    printf("--- HOOK GLXSWAPINTERVALSGI\n");
    _glXSwapIntervalSGI = (void*)ret;
    return (__GLXextFuncPtr)glXSwapIntervalSGI;
    } else if (!strcmp((const char*)procname, "glXSwapIntervalMESA")) {
    printf("--- HOOK GLXSWAPINTERVALMESA\n");
    _glXSwapIntervalMESA = (void*)ret;
    return (__GLXextFuncPtr)glXSwapIntervalMESA;
    }
    return ret;
    }

    __GLXextFuncPtr glXGetProcAddressEXT(const GLubyte *procname)
    {
    __GLXextFuncPtr ret = NULL;
    if (!_glXGetProcAddressEXT) _glXGetProcAddressEXT = _dl_sym(RTLD_NEXT, __FUNCTION__, glXGetProcAddressEXT);
    if (!(ret = _glXGetProcAddressEXT(procname))) return ret;
    return hookedProc(procname, ret);
    }

    __GLXextFuncPtr glXGetProcAddressARB(const GLubyte *procname)
    {
    __GLXextFuncPtr ret = NULL;
    if (!_glXGetProcAddressARB) _glXGetProcAddressARB = _dl_sym(RTLD_NEXT, __FUNCTION__, glXGetProcAddressARB);
    if (!(ret = _glXGetProcAddressARB(procname))) return ret;
    return hookedProc(procname, ret);
    }

    __GLXextFuncPtr glXGetProcAddress(const GLubyte *procname)
    {
    __GLXextFuncPtr ret = NULL;
    if (!_glXGetProcAddress) _glXGetProcAddress = _dl_sym(RTLD_NEXT, __FUNCTION__, glXGetProcAddress);
    if (!(ret = _glXGetProcAddress(procname))) return ret;
    return hookedProc(procname, ret);
    }

    void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
    {
    static int once = 0;
    static int counter = 0;
    if (!_glXSwapBuffers) _glXSwapBuffers = _dl_sym(RTLD_NEXT, __FUNCTION__ ,glXSwapBuffers);

    if (!once) {
    const char *swap = getenv("_GLVSYNC_INTERVAL");
    if (swap) SYNC_INTERVAL = strtol(swap, NULL, 10);
    }

    if (_glXSwapIntervalEXT) {
    if (!once) printf("--- FORCE SWAP (EXT)\n");
    _glXSwapIntervalEXT(dpy, drawable, SYNC_INTERVAL);
    } else if (_glXSwapIntervalSGI) {
    if (!once) printf("--- FORCE SWAP (SGI)\n");
    _glXSwapIntervalSGI(SYNC_INTERVAL);
    } else if (_glXSwapIntervalMESA) {
    if (!once) printf("--- FORCE SWAP (MESA)\n");
    _glXSwapIntervalMESA(SYNC_INTERVAL);
    }

    _glXSwapBuffers(dpy, drawable);
    once = 1;
    }

    void *dlsym(void *handle, const char *symbol)
    {
    void *ret = NULL;
    if (symbol && !strcmp(symbol, "dlsym")) return dlsym;
    if (!(ret = _dl_sym(handle, symbol, dlsym))) return ret;

    if (!strcmp(symbol, "glXGetProcAddressARB")) {
    printf("--- HOOK GLXGETPROCADDRESSARB\n");
    _glXGetProcAddressARB = ret;
    return glXGetProcAddressARB;
    } else if (!strcmp(symbol, "glXGetProcAddress")) {
    printf("--- HOOK GLXGETPROCADDRESS\n");
    _glXGetProcAddress = ret;
    return glXGetProcAddress;
    } else if (!strcmp(symbol, "glXGetProcAddressEXT")) {
    printf("--- HOOK GLXGETPROCADDRESSEXT\n");
    _glXGetProcAddressEXT = ret;
    return glXGetProcAddressEXT;
    } else if (!strcmp(symbol, "glXSwapBuffers")) {
    printf("--- HOOK GLXSWAPBUFFERS\n");
    _glXSwapBuffers = ret;
    return glXSwapBuffers;
    } else if (!strcmp(symbol, "glXSwapIntervalEXT")) {
    printf("--- HOOK GLXSWAPINTERVALEXT\n");
    _glXSwapIntervalEXT = ret;
    return _glXSwapIntervalEXT;
    } else if (!strcmp(symbol, "glXSwapIntervalSGI")) {
    printf("--- HOOK GLXSWAPINTERVALSGI\n");
    _glXSwapIntervalSGI = ret;
    return _glXSwapIntervalSGI;
    } else if (!strcmp(symbol, "glXSwapIntervalMESA")) {
    printf("--- HOOK GLXSWAPINTERVALMESA\n");
    _glXSwapIntervalMESA = ret;
    return _glXSwapIntervalMESA;
    }
    return ret;
    }

    /* vim: set ts=8 sw=3 tw=0 :*/