From a94861b09ae9e7e8edce1eb518cb5e5f20e328a3 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Thu, 31 Dec 2020 16:52:07 +0100 Subject: commit it --- Makefile | 12 +++++++++ README | 8 ++++++ copy_pixels_swap_hack.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ test_copy_to_front.c | 44 ++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100644 copy_pixels_swap_hack.c create mode 100644 test_copy_to_front.c 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 diff --git a/README b/README new file mode 100644 index 0000000..d1334b1 --- /dev/null +++ b/README @@ -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 +#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); + } +} 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 +#include +#include + +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; +} -- cgit v1.2.3