1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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 <dlfcn.h>
#include <GL/gl.h>
#include <GL/glx.h>
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);
}
}
|