diff options
author | Wolfgang Draxinger <code@datenwolf.net> | 2020-12-31 16:52:07 +0100 |
---|---|---|
committer | Wolfgang Draxinger <code@datenwolf.net> | 2020-12-31 16:52:07 +0100 |
commit | a94861b09ae9e7e8edce1eb518cb5e5f20e328a3 (patch) | |
tree | 1840154012f1cc9212384ceebf14c15c66b95eb5 | |
download | copy_pixels_swap_hack-a94861b09ae9e7e8edce1eb518cb5e5f20e328a3.tar.gz copy_pixels_swap_hack-a94861b09ae9e7e8edce1eb518cb5e5f20e328a3.tar.bz2 |
commit it
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | README | 8 | ||||
-rw-r--r-- | copy_pixels_swap_hack.c | 67 | ||||
-rw-r--r-- | test_copy_to_front.c | 44 |
4 files changed, 131 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4e4429b --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +.PHONY: all clean + +all: copy_pixels_swap_hack.so test_copy_to_front + +clean: + -rm copy_pixels_swap_hack.so test_copy_to_front + +copy_pixels_swap_hack.so: copy_pixels_swap_hack.c + $(CC) -shared -o $@ -O2 -fPIC $< -ldl + +test_copy_to_front: test_copy_to_front.c + $(CC) -o $@ -O2 -fPIE $< -lGL -lglut -lm @@ -0,0 +1,8 @@ +Call glXSwapBuffers instead of glCopyPixels if OpenGL read and draw buffers +would perform a copy from back to front buffer. + +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. 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 <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); + } +} diff --git a/test_copy_to_front.c b/test_copy_to_front.c new file mode 100644 index 0000000..3d69f81 --- /dev/null +++ b/test_copy_to_front.c @@ -0,0 +1,44 @@ +#include <GL/glut.h> +#include <GL/gl.h> +#include <math.h> + +static void display(void) +{ + static float a = 0; + + int const win_w = glutGet(GLUT_WINDOW_WIDTH); + int const win_h = glutGet(GLUT_WINDOW_HEIGHT); + float const win_a = (float)win_w/(float)win_h; + + glDrawBuffer(GL_BACK); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, win_w, win_h); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-win_a, win_a, -1, 1, 1, 5); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0,0,-3); + glRotatef( a = fmodf(a + 1, 360) , 0,1,0); + + glutWireTeapot(1); + + glFlush(); + glDrawBuffer(GL_FRONT); + glReadBuffer(GL_BACK); + glCopyPixels(0, 0, win_w, win_h, GL_COLOR); + glFinish(); +} + +int main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); + glutCreateWindow("Test copy back->front instead of buffer swap"); + glutDisplayFunc(display); + glutIdleFunc(glutPostRedisplay); + + glutMainLoop(); + return 0; +} |