aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Draxinger <code@datenwolf.net>2020-12-31 16:52:07 +0100
committerWolfgang Draxinger <code@datenwolf.net>2020-12-31 16:52:07 +0100
commita94861b09ae9e7e8edce1eb518cb5e5f20e328a3 (patch)
tree1840154012f1cc9212384ceebf14c15c66b95eb5
downloadcopy_pixels_swap_hack-a94861b09ae9e7e8edce1eb518cb5e5f20e328a3.tar.gz
copy_pixels_swap_hack-a94861b09ae9e7e8edce1eb518cb5e5f20e328a3.tar.bz2
commit it
-rw-r--r--Makefile12
-rw-r--r--README8
-rw-r--r--copy_pixels_swap_hack.c67
-rw-r--r--test_copy_to_front.c44
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
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 <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;
+}