summaryrefslogtreecommitdiff
path: root/hooks.h
diff options
context:
space:
mode:
authorJari Vetoniemi <mailroxas@gmail.com>2017-01-23 09:36:20 +0200
committerJari Vetoniemi <mailroxas@gmail.com>2017-01-23 09:39:41 +0200
commit0b35be65b43f88f0a17a6f8830a52415c3ff1aa1 (patch)
tree75fa9155be8443ae6050d456db9b4ce0f2c83022 /hooks.h
parentd69f53b735eec46a802e5ffaff9ee4dbc0ccb391 (diff)
Split code a bit, wrangle OpenGL
Split system function hooks into hooks.h Wrangle opengl functions instead of trying to use them directly.
Diffstat (limited to 'hooks.h')
-rw-r--r--hooks.h172
1 files changed, 172 insertions, 0 deletions
diff --git a/hooks.h b/hooks.h
new file mode 100644
index 0000000..a96fcae
--- /dev/null
+++ b/hooks.h
@@ -0,0 +1,172 @@
+#pragma once
+
+static void* (*_dlsym)(void*, const char*) = NULL;
+static EGLBoolean (*_eglSwapBuffers)(EGLDisplay, EGLSurface) = NULL;
+static __eglMustCastToProperFunctionPointerType (*_eglGetProcAddress)(const char*) = NULL;
+static void (*_glXSwapBuffers)(Display*, GLXDrawable) = NULL;
+static __GLXextFuncPtr (*_glXGetProcAddress)(const GLubyte*) = NULL;
+static __GLXextFuncPtr (*_glXGetProcAddressARB)(const GLubyte*) = NULL;
+static snd_pcm_sframes_t (*_snd_pcm_writei)(snd_pcm_t*, const void*, snd_pcm_uframes_t) = NULL;
+static snd_pcm_sframes_t (*_snd_pcm_writen)(snd_pcm_t*, void**, snd_pcm_uframes_t) = NULL;
+static snd_pcm_sframes_t (*_snd_pcm_mmap_writei)(snd_pcm_t*, const void*, snd_pcm_uframes_t) = NULL;
+static snd_pcm_sframes_t (*_snd_pcm_mmap_writen)(snd_pcm_t*, void**, snd_pcm_uframes_t) = NULL;
+static int (*_clock_gettime)(clockid_t, struct timespec*) = NULL;
+static void* store_real_symbol_and_return_fake_symbol(const char*, void*);
+static void hook_function(void**, const char*, const bool);
+
+#define HOOK(x) hook_function((void**)&_##x, #x, false)
+
+static uint64_t
+get_time_ns(void)
+{
+ struct timespec ts;
+ HOOK(clock_gettime);
+ _clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (uint64_t)ts.tv_sec * (uint64_t)1e9 + (uint64_t)ts.tv_nsec;
+}
+
+EGLBoolean
+eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
+{
+ HOOK(eglSwapBuffers);
+ swap_buffers();
+ return _eglSwapBuffers(dpy, surface);
+}
+
+__eglMustCastToProperFunctionPointerType
+eglGetProcAddress(const char *procname)
+{
+ HOOK(eglGetProcAddress);
+ return (_eglGetProcAddress ? store_real_symbol_and_return_fake_symbol(procname, _eglGetProcAddress(procname)) : NULL);
+}
+
+void
+glXSwapBuffers(Display *dpy, GLXDrawable drawable)
+{
+ HOOK(glXSwapBuffers);
+ swap_buffers();
+ _glXSwapBuffers(dpy, drawable);
+}
+
+__GLXextFuncPtr
+glXGetProcAddressARB(const GLubyte *procname)
+{
+ HOOK(glXGetProcAddressARB);
+ return (_glXGetProcAddressARB ? store_real_symbol_and_return_fake_symbol((const char*)procname, _glXGetProcAddressARB(procname)) : NULL);
+}
+
+__GLXextFuncPtr
+glXGetProcAddress(const GLubyte *procname)
+{
+ HOOK(glXGetProcAddress);
+ return (_glXGetProcAddress ? store_real_symbol_and_return_fake_symbol((const char*)procname, _glXGetProcAddress(procname)) : NULL);
+}
+
+snd_pcm_sframes_t
+snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
+{
+ HOOK(snd_pcm_writei);
+ alsa_writei(pcm, buffer, size, __func__);
+ return _snd_pcm_writei(pcm, buffer, size);
+}
+
+snd_pcm_sframes_t
+snd_pcm_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+{
+ HOOK(snd_pcm_writen);
+ // FIXME: Implement
+ return _snd_pcm_writen(pcm, bufs, size);
+}
+
+snd_pcm_sframes_t
+snd_pcm_mmap_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size)
+{
+ HOOK(snd_pcm_mmap_writei);
+ alsa_writei(pcm, buffer, size, __func__);
+ return _snd_pcm_mmap_writei(pcm, buffer, size);
+}
+
+snd_pcm_sframes_t
+snd_pcm_mmap_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
+{
+ HOOK(snd_pcm_mmap_writen);
+ // FIXME: Implement
+ return _snd_pcm_mmap_writen(pcm, bufs, size);
+}
+
+int
+clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+ HOOK(clock_gettime);
+
+ if ((clk_id == CLOCK_MONOTONIC || clk_id == CLOCK_MONOTONIC_RAW)) {
+ static __thread uint64_t base;
+ const uint64_t current = get_time_ns();
+ if (!base) base = current;
+ const uint64_t fake = base + (current - base) * SPEED_HACK;
+ tp->tv_sec = fake / (uint64_t)1e9;
+ tp->tv_nsec = (fake % (uint64_t)1e9);
+ return 0;
+ }
+
+ return _clock_gettime(clk_id, tp);
+}
+
+#define HOOK_DLSYM(x) hook_function((void**)&_##x, #x, true)
+
+void*
+dlsym(void *handle, const char *symbol)
+{
+ HOOK_DLSYM(dlsym);
+
+ if (!strcmp(symbol, "dlsym"))
+ return dlsym;
+
+ return store_real_symbol_and_return_fake_symbol(symbol, _dlsym(handle, symbol));
+}
+
+static void*
+store_real_symbol_and_return_fake_symbol(const char *symbol, void *ret)
+{
+ if (!ret || !symbol)
+ return ret;
+
+ if (0) {}
+#define SET_IF_NOT_HOOKED(x, y) do { if (!_##x) { _##x = y; WARNX("SET %s to %p", #x, y); } } while (0)
+#define FAKE_SYMBOL(x) else if (!strcmp(symbol, #x)) { SET_IF_NOT_HOOKED(x, ret); return x; }
+ FAKE_SYMBOL(eglSwapBuffers)
+ FAKE_SYMBOL(eglGetProcAddress)
+ FAKE_SYMBOL(glXSwapBuffers)
+ FAKE_SYMBOL(glXGetProcAddressARB)
+ FAKE_SYMBOL(glXGetProcAddress)
+ FAKE_SYMBOL(snd_pcm_writei)
+ FAKE_SYMBOL(snd_pcm_writen)
+ FAKE_SYMBOL(snd_pcm_mmap_writei)
+ FAKE_SYMBOL(snd_pcm_mmap_writen)
+ FAKE_SYMBOL(clock_gettime)
+#undef FAKE_SYMBOL
+#undef SET_IF_NOT_HOOKED
+
+ return ret;
+}
+
+static void
+hook_function(void **ptr, const char *name, const bool versioned)
+{
+ if (*ptr)
+ return;
+
+ if (versioned) {
+ const char *versions[] = { "GLIBC_2.0", "GLIBC_2.2.5", NULL };
+ for (size_t i = 0; !*ptr && versions[i]; ++i)
+ *ptr = dlvsym(RTLD_NEXT, name, versions[i]);
+ } else {
+ HOOK_DLSYM(dlsym);
+ *ptr = _dlsym(RTLD_NEXT, name);
+ }
+
+ if (!*ptr)
+ ERRX(EXIT_FAILURE, "HOOK FAIL %s", name);
+
+ WARNX("HOOK %s", name);
+}