From a94861b09ae9e7e8edce1eb518cb5e5f20e328a3 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Thu, 31 Dec 2020 16:52:07 +0100 Subject: commit it --- copy_pixels_swap_hack.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 copy_pixels_swap_hack.c (limited to 'copy_pixels_swap_hack.c') diff --git a/copy_pixels_swap_hack.c b/copy_pixels_swap_hack.c new file mode 100644 index 0000000..653eeaf --- /dev/null +++ b/copy_pixels_swap_hack.c @@ -0,0 +1,67 @@ +// copy_pixels_swap_hack.c +// +// Call glXSwapBuffers instead of glCopyPixels if OpenGL read and draw buffers +// would perform a copy from back to front buffer. +// +// compile with +// gcc -shared -o copy_pixels_swap_hack.so -fPIC -O2 copy_pixels_swap.c -ldl +// +// use with +// LD_PRELOAD=copy_pixels_swap_hack.so ${YOUR_PROGRAM} +// +// Refer to the ld.so(8) manpage for the path at which the preloaded shared +// objects is searched for. +#define _GNU_SOURCE +#include +#include +#include +void glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) +{ + static int first = 1; + static Display* (*glx_get_current_display)(void) = NULL; + static GLXDrawable (*glx_get_current_drawable)(void) = NULL; + static void (*glx_swap_buffers)(Display*,GLXDrawable) = NULL; + static void (*gl_copy_pixels)(GLint,GLint,GLsizei,GLsizei,GLenum) = NULL; + static void (*gl_get_integerv)(GLenum,GLint*) = NULL; + static void (*gl_draw_buffer)(GLenum) = NULL; + static void (*gl_read_buffer)(GLenum) = NULL; + if( first ){ + *(void**)(&glx_get_current_display) = dlsym(RTLD_NEXT, "glXGetCurrentDisplay"); + *(void**)(&glx_get_current_drawable) = dlsym(RTLD_NEXT, "glXGetCurrentDrawable"); + *(void**)(&glx_swap_buffers) = dlsym(RTLD_NEXT, "glXSwapBuffers"); + *(void**)(&gl_copy_pixels) = dlsym(RTLD_NEXT, "glCopyPixels"); + *(void**)(&gl_get_integerv) = dlsym(RTLD_NEXT, "glGetIntegerv"); + *(void**)(&gl_draw_buffer) = dlsym(RTLD_NEXT, "glDrawBuffer"); + *(void**)(&gl_read_buffer) = dlsym(RTLD_NEXT, "glReadBuffer"); + first = 0; + } + + Display *dpy; + GLXDrawable drw; + if( !glx_get_current_display || !glx_get_current_drawable + || !gl_get_integerv || !gl_copy_pixels || !glx_swap_buffers + || !gl_draw_buffer || !gl_read_buffer + || !(dpy = glx_get_current_display()) + || !(drw = glx_get_current_drawable()) + ){ + return; + } + + GLint buffer_draw = 0; + GLint buffer_read = ~0; + gl_get_integerv(GL_DRAW_BUFFER, &buffer_draw); + gl_get_integerv(GL_READ_BUFFER, &buffer_read); + if( GL_COLOR == type + && buffer_draw == GL_FRONT + && buffer_read == GL_BACK + ){ + glx_swap_buffers(dpy, drw); + gl_draw_buffer(GL_BACK); + gl_read_buffer(GL_FRONT); + gl_copy_pixels(x,y,width,height,type); + gl_draw_buffer(GL_FRONT); + gl_read_buffer(GL_BACK); + } else { + gl_copy_pixels(x,y,width,height,type); + } +} -- cgit v1.2.3