Import primus_0~20150328.orig.tar.gz
authorVincent Cheng <vcheng@debian.org>
Sun, 26 Jul 2015 03:42:42 +0000 (20:42 -0700)
committerVincent Cheng <vcheng@debian.org>
Sun, 26 Jul 2015 03:42:42 +0000 (20:42 -0700)
[dgit import orig primus_0~20150328.orig.tar.gz]

14 files changed:
LICENSE.txt [new file with mode: 0644]
Makefile [new file with mode: 0644]
README.md [new file with mode: 0644]
gl-needed.def [new file with mode: 0644]
gl-passthru.def [new file with mode: 0644]
glext-passthru.def [new file with mode: 0644]
glx-dpyredir.def [new file with mode: 0644]
glx-reimpl.def [new file with mode: 0644]
glxext-reimpl.def [new file with mode: 0644]
libglfork.cpp [new file with mode: 0644]
primus.bash-completion [new file with mode: 0644]
primusrun [new file with mode: 0755]
primusrun.1 [new file with mode: 0644]
technotes.md [new file with mode: 0644]

diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644 (file)
index 0000000..c3a839a
--- /dev/null
@@ -0,0 +1,13 @@
+Copyright (c) 2012, Alexander Monakov  <amonakov@gmail.com>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..ab37e6e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,33 @@
+CXX      ?= g++
+CXXFLAGS ?= -Wall -g
+
+CXXFLAGS += -Werror=missing-declarations
+CXXFLAGS += -Werror=attributes
+
+# On multilib systems, this needs to point to distribution-specific library
+# subdir like in /usr (lib or lib64 for 64-bit, lib32 or lib for 32-bit)
+LIBDIR   ?= lib
+
+BUMBLEBEE_SOCKET   ?= /var/run/bumblebee.socket
+PRIMUS_SYNC        ?= 0
+PRIMUS_VERBOSE     ?= 1
+PRIMUS_UPLOAD      ?= 0
+PRIMUS_SLEEP       ?= 90
+PRIMUS_DISPLAY     ?= :8
+PRIMUS_LOAD_GLOBAL ?= libglapi.so.0
+PRIMUS_libGLa      ?= /usr/$$LIB/nvidia/libGL.so.1
+PRIMUS_libGLd      ?= /usr/$$LIB/libGL.so.1
+
+CXXFLAGS += -DBUMBLEBEE_SOCKET='"$(BUMBLEBEE_SOCKET)"'
+CXXFLAGS += -DPRIMUS_SYNC='"$(PRIMUS_SYNC)"'
+CXXFLAGS += -DPRIMUS_VERBOSE='"$(PRIMUS_VERBOSE)"'
+CXXFLAGS += -DPRIMUS_UPLOAD='"$(PRIMUS_UPLOAD)"'
+CXXFLAGS += -DPRIMUS_SLEEP='"$(PRIMUS_SLEEP)"'
+CXXFLAGS += -DPRIMUS_DISPLAY='"$(PRIMUS_DISPLAY)"'
+CXXFLAGS += -DPRIMUS_LOAD_GLOBAL='"$(PRIMUS_LOAD_GLOBAL)"'
+CXXFLAGS += -DPRIMUS_libGLa='"$(PRIMUS_libGLa)"'
+CXXFLAGS += -DPRIMUS_libGLd='"$(PRIMUS_libGLd)"'
+
+$(LIBDIR)/libGL.so.1: libglfork.cpp
+       mkdir -p $(LIBDIR)
+       $(CXX) $(CPPFLAGS) $(CXXFLAGS) -fvisibility=hidden -fPIC -shared -Wl,-Bsymbolic -o $@ $< -lX11 -lpthread -lrt
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..6adfd30
--- /dev/null
+++ b/README.md
@@ -0,0 +1,73 @@
+primus
+======
+
+Primus is a shared library that provides OpenGL and GLX APIs and
+implements low-overhead
+local-only client-side OpenGL offloading via GLX forking, similar to
+VirtualGL.  It intercepts GLX calls and redirects GL rendering to a
+secondary X display, presumably driven by a faster GPU. On swapping
+buffers, rendered contents are read back using a PBO and copied onto
+the drawable it was supposed to be rendered on in the first place.
+For more information, refer to [technotes.md]
+(https://github.com/amonakov/primus/blob/master/technotes.md).
+
+To use, install or build from source and use `primusrun` wrapper script.
+
+In distributions
+----------------
+
+* Arch: [primus-git](https://aur.archlinux.org/packages.php?ID=63239)
+  and [lib32-primus-git](https://aur.archlinux.org/packages.php?ID=63240)
+  in AUR
+* Gentoo: `primus-9999.ebuild` in the `bumblebee` overlay
+* Ubuntu: in the [Bumblebee PPA](https://launchpad.net/~bumblebee/+archive/stable)
+
+Building for multilib (32-bit + 64-bit) systems
+-----------------------------------------------
+
+    LIBDIR=lib make && CXX=g++\ -m32 LIBDIR=lib32 make
+
+Adjust `LIBDIR` variables above as appropriate for your distribution
+(reflecting how `/usr/lib*` are named):
+
+* Arch needs `lib` and `lib32` as above
+* Gentoo needs `lib64` and `lib32`
+* RPM-based may need `lib64` and `lib`
+* Debian (with multiarch) needs `lib/x86_64-linux-gnu` and `lib/i386-linux-gnu`
+* Ubuntu (with multiarch) seems rather inconsistent.  The dynamic linker
+  expands `$LIB` to `x86_64-linux-gnu`/`i386-linux-gnu` (without `lib/`), but
+  Nvidia drivers are installed into `/usr/lib{,32}/nvidia-current`. Something
+  like the following is needed:
+
+        export PRIMUS_libGLd='/usr/lib/$$LIB/mesa/libGL.so.1'
+        LIBDIR=x86_64-linux-gnu make
+        LIBDIR=i386-linux-gnu CXX=g++\ -m32 make
+        unset PRIMUS_libGLd
+
+  Starting from 13.04, Ubuntu needs the same `LIBDIR` paths as Debian (with
+  leading `lib/`); consequently, `lib/` in `PRIMUS_libGLd` should be omitted.
+
+  Furthermore, `libnvidia-tls.so` is not present in default shared library
+  search directories.  Uncomment the corresponding line in `primusrun`.
+
+Issues under compositing WMs
+----------------------------
+
+Since compositing hurts performance, invoking primus when a compositing WM is
+active is not recommended.  If you need to use primus with compositing and see
+flickering or bad performance, synchronizing primus' display thread with the
+application's rendering thread may help (can anyone investigate why?):
+
+    PRIMUS_SYNC=1 primusrun ...
+
+This makes primus display the previously rendered frame. Alternatively,
+with `PRIMUS_SYNC=2` primus will display the latest rendered frame, trading
+frame rate for reduced visual latency.
+
+FAQ
+---
+
+Q: Performance does not exceed 60 fps, I was getting more with optirun/VirtualGL.  
+A: This is the effect of vblank synchronisation. For benchmarking, you can use
+`vblank_mode=0 primusrun ...`, but in practice this will probably only waste power,
+as your LCD panel does not display more than 60 frames per second anyway.
diff --git a/gl-needed.def b/gl-needed.def
new file mode 100644 (file)
index 0000000..907eed6
--- /dev/null
@@ -0,0 +1,12 @@
+// OpenGL extension functions needed by primus itself
+DEF_GLX_PROTO(void,     glGenBuffers,    (GLsizei n, GLuint *buffers))
+DEF_GLX_PROTO(void,     glDeleteBuffers, (GLsizei n, const GLuint *buffers))
+DEF_GLX_PROTO(void,     glBindBuffer, (GLenum target, GLuint buffer))
+DEF_GLX_PROTO(void,     glBufferData, (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage))
+DEF_GLX_PROTO(void,     glBufferSubData, (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data))
+DEF_GLX_PROTO(GLvoid*,  glMapBuffer,  (GLenum target, GLenum access))
+DEF_GLX_PROTO(GLboolean,glUnmapBuffer,(GLenum target))
+
+DEF_GLX_PROTO(GLsync,   glFenceSync, (GLenum condition, GLbitfield flags))
+DEF_GLX_PROTO(void,     glDeleteSync,(GLsync sync))
+DEF_GLX_PROTO(void,     glWaitSync,  (GLsync sync, GLbitfield flags, GLuint64 timeout))
diff --git a/gl-passthru.def b/gl-passthru.def
new file mode 100644 (file)
index 0000000..8dcddae
--- /dev/null
@@ -0,0 +1,455 @@
+// Prototypes for auto-generating forwarders for OpenGL functions
+DEF_GLX_PROTO(void, glClearIndex,(GLfloat c), c)
+DEF_GLX_PROTO(void, glClearColor,(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glClear,(GLbitfield mask), mask)
+DEF_GLX_PROTO(void, glIndexMask,(GLuint mask), mask)
+DEF_GLX_PROTO(void, glColorMask,(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glAlphaFunc,(GLenum func, GLclampf ref), func, ref)
+DEF_GLX_PROTO(void, glBlendFunc,(GLenum sfactor, GLenum dfactor), sfactor, dfactor)
+DEF_GLX_PROTO(void, glLogicOp,(GLenum opcode), opcode)
+DEF_GLX_PROTO(void, glCullFace,(GLenum mode), mode)
+DEF_GLX_PROTO(void, glFrontFace,(GLenum mode), mode)
+DEF_GLX_PROTO(void, glPointSize,(GLfloat size), size)
+DEF_GLX_PROTO(void, glLineWidth,(GLfloat width), width)
+DEF_GLX_PROTO(void, glLineStipple,(GLint factor, GLushort pattern), factor, pattern)
+DEF_GLX_PROTO(void, glPolygonMode,(GLenum face, GLenum mode), face, mode)
+DEF_GLX_PROTO(void, glPolygonOffset,(GLfloat factor, GLfloat units), factor, units)
+DEF_GLX_PROTO(void, glPolygonStipple,(const GLubyte *mask), mask)
+DEF_GLX_PROTO(void, glGetPolygonStipple,(GLubyte *mask), mask)
+DEF_GLX_PROTO(void, glEdgeFlag,(GLboolean flag), flag)
+DEF_GLX_PROTO(void, glEdgeFlagv,(const GLboolean *flag), flag)
+DEF_GLX_PROTO(void, glScissor,(GLint x, GLint y, GLsizei width, GLsizei height), x, y, width, height)
+DEF_GLX_PROTO(void, glClipPlane,(GLenum plane, const GLdouble *equation), plane, equation)
+DEF_GLX_PROTO(void, glGetClipPlane,(GLenum plane, GLdouble *equation), plane, equation)
+DEF_GLX_PROTO(void, glDrawBuffer,(GLenum mode), mode)
+DEF_GLX_PROTO(void, glReadBuffer,(GLenum mode), mode)
+DEF_GLX_PROTO(void, glEnable,(GLenum cap), cap)
+DEF_GLX_PROTO(void, glDisable,(GLenum cap), cap)
+DEF_GLX_PROTO(GLboolean, glIsEnabled,(GLenum cap), cap)
+DEF_GLX_PROTO(void, glEnableClientState,(GLenum cap), cap)
+DEF_GLX_PROTO(void, glDisableClientState,(GLenum cap), cap)
+DEF_GLX_PROTO(void, glGetBooleanv,(GLenum pname, GLboolean *params), pname, params)
+DEF_GLX_PROTO(void, glGetDoublev,(GLenum pname, GLdouble *params), pname, params)
+DEF_GLX_PROTO(void, glGetFloatv,(GLenum pname, GLfloat *params), pname, params)
+DEF_GLX_PROTO(void, glGetIntegerv,(GLenum pname, GLint *params), pname, params)
+DEF_GLX_PROTO(void, glPushAttrib,(GLbitfield mask), mask)
+DEF_GLX_PROTO(void, glPopAttrib,(void))
+DEF_GLX_PROTO(void, glPushClientAttrib,(GLbitfield mask), mask)
+DEF_GLX_PROTO(void, glPopClientAttrib,(void))
+DEF_GLX_PROTO(GLint, glRenderMode,(GLenum mode), mode)
+DEF_GLX_PROTO(GLenum, glGetError,(void))
+DEF_GLX_PROTO(const GLubyte *, glGetString,(GLenum name), name)
+DEF_GLX_PROTO(void, glFinish,(void))
+DEF_GLX_PROTO(void, glFlush,(void))
+DEF_GLX_PROTO(void, glHint,(GLenum target, GLenum mode), target, mode)
+DEF_GLX_PROTO(void, glClearDepth,(GLclampd depth), depth)
+DEF_GLX_PROTO(void, glDepthFunc,(GLenum func), func)
+DEF_GLX_PROTO(void, glDepthMask,(GLboolean flag), flag)
+DEF_GLX_PROTO(void, glDepthRange,(GLclampd near_val, GLclampd far_val), near_val, far_val)
+DEF_GLX_PROTO(void, glClearAccum,(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glAccum,(GLenum op, GLfloat value), op, value)
+DEF_GLX_PROTO(void, glMatrixMode,(GLenum mode), mode)
+DEF_GLX_PROTO(void, glOrtho,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val), left, right, bottom, top, near_val, far_val)
+DEF_GLX_PROTO(void, glFrustum,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val), left, right, bottom, top, near_val, far_val)
+DEF_GLX_PROTO(void, glViewport,(GLint x, GLint y, GLsizei width, GLsizei height), x, y, width, height)
+DEF_GLX_PROTO(void, glPushMatrix,(void))
+DEF_GLX_PROTO(void, glPopMatrix,(void))
+DEF_GLX_PROTO(void, glLoadIdentity,(void))
+DEF_GLX_PROTO(void, glLoadMatrixd,(const GLdouble *m), m)
+DEF_GLX_PROTO(void, glLoadMatrixf,(const GLfloat *m), m)
+DEF_GLX_PROTO(void, glMultMatrixd,(const GLdouble *m), m)
+DEF_GLX_PROTO(void, glMultMatrixf,(const GLfloat *m), m)
+DEF_GLX_PROTO(void, glRotated,(GLdouble angle, GLdouble x, GLdouble y, GLdouble z), angle, x, y, z)
+DEF_GLX_PROTO(void, glRotatef,(GLfloat angle, GLfloat x, GLfloat y, GLfloat z), angle, x, y, z)
+DEF_GLX_PROTO(void, glScaled,(GLdouble x, GLdouble y, GLdouble z), x, y, z)
+DEF_GLX_PROTO(void, glScalef,(GLfloat x, GLfloat y, GLfloat z), x, y, z)
+DEF_GLX_PROTO(void, glTranslated,(GLdouble x, GLdouble y, GLdouble z), x, y, z)
+DEF_GLX_PROTO(void, glTranslatef,(GLfloat x, GLfloat y, GLfloat z), x, y, z)
+DEF_GLX_PROTO(GLboolean, glIsList,(GLuint list), list)
+DEF_GLX_PROTO(void, glDeleteLists,(GLuint list, GLsizei range), list, range)
+DEF_GLX_PROTO(GLuint, glGenLists,(GLsizei range), range)
+DEF_GLX_PROTO(void, glNewList,(GLuint list, GLenum mode), list, mode)
+DEF_GLX_PROTO(void, glEndList,(void))
+DEF_GLX_PROTO(void, glCallList,(GLuint list), list)
+DEF_GLX_PROTO(void, glCallLists,(GLsizei n, GLenum type, const GLvoid *lists), n, type, lists)
+DEF_GLX_PROTO(void, glListBase,(GLuint base), base)
+DEF_GLX_PROTO(void, glBegin,(GLenum mode), mode)
+DEF_GLX_PROTO(void, glEnd,(void))
+DEF_GLX_PROTO(void, glVertex2d,(GLdouble x, GLdouble y), x, y)
+DEF_GLX_PROTO(void, glVertex2f,(GLfloat x, GLfloat y), x, y)
+DEF_GLX_PROTO(void, glVertex2i,(GLint x, GLint y), x, y)
+DEF_GLX_PROTO(void, glVertex2s,(GLshort x, GLshort y), x, y)
+DEF_GLX_PROTO(void, glVertex3d,(GLdouble x, GLdouble y, GLdouble z), x, y, z)
+DEF_GLX_PROTO(void, glVertex3f,(GLfloat x, GLfloat y, GLfloat z), x, y, z)
+DEF_GLX_PROTO(void, glVertex3i,(GLint x, GLint y, GLint z), x, y, z)
+DEF_GLX_PROTO(void, glVertex3s,(GLshort x, GLshort y, GLshort z), x, y, z)
+DEF_GLX_PROTO(void, glVertex4d,(GLdouble x, GLdouble y, GLdouble z, GLdouble w), x, y, z, w)
+DEF_GLX_PROTO(void, glVertex4f,(GLfloat x, GLfloat y, GLfloat z, GLfloat w), x, y, z, w)
+DEF_GLX_PROTO(void, glVertex4i,(GLint x, GLint y, GLint z, GLint w), x, y, z, w)
+DEF_GLX_PROTO(void, glVertex4s,(GLshort x, GLshort y, GLshort z, GLshort w), x, y, z, w)
+DEF_GLX_PROTO(void, glVertex2dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glVertex2fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glVertex2iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glVertex2sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glVertex3dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glVertex3fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glVertex3iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glVertex3sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glVertex4dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glVertex4fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glVertex4iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glVertex4sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glNormal3b,(GLbyte nx, GLbyte ny, GLbyte nz), nx, ny, nz)
+DEF_GLX_PROTO(void, glNormal3d,(GLdouble nx, GLdouble ny, GLdouble nz), nx, ny, nz)
+DEF_GLX_PROTO(void, glNormal3f,(GLfloat nx, GLfloat ny, GLfloat nz), nx, ny, nz)
+DEF_GLX_PROTO(void, glNormal3i,(GLint nx, GLint ny, GLint nz), nx, ny, nz)
+DEF_GLX_PROTO(void, glNormal3s,(GLshort nx, GLshort ny, GLshort nz), nx, ny, nz)
+DEF_GLX_PROTO(void, glNormal3bv,(const GLbyte *v), v)
+DEF_GLX_PROTO(void, glNormal3dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glNormal3fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glNormal3iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glNormal3sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glIndexd,(GLdouble c), c)
+DEF_GLX_PROTO(void, glIndexf,(GLfloat c), c)
+DEF_GLX_PROTO(void, glIndexi,(GLint c), c)
+DEF_GLX_PROTO(void, glIndexs,(GLshort c), c)
+DEF_GLX_PROTO(void, glIndexub,(GLubyte c), c)
+DEF_GLX_PROTO(void, glIndexdv,(const GLdouble *c), c)
+DEF_GLX_PROTO(void, glIndexfv,(const GLfloat *c), c)
+DEF_GLX_PROTO(void, glIndexiv,(const GLint *c), c)
+DEF_GLX_PROTO(void, glIndexsv,(const GLshort *c), c)
+DEF_GLX_PROTO(void, glIndexubv,(const GLubyte *c), c)
+DEF_GLX_PROTO(void, glColor3b,(GLbyte red, GLbyte green, GLbyte blue), red, green, blue)
+DEF_GLX_PROTO(void, glColor3d,(GLdouble red, GLdouble green, GLdouble blue), red, green, blue)
+DEF_GLX_PROTO(void, glColor3f,(GLfloat red, GLfloat green, GLfloat blue), red, green, blue)
+DEF_GLX_PROTO(void, glColor3i,(GLint red, GLint green, GLint blue), red, green, blue)
+DEF_GLX_PROTO(void, glColor3s,(GLshort red, GLshort green, GLshort blue), red, green, blue)
+DEF_GLX_PROTO(void, glColor3ub,(GLubyte red, GLubyte green, GLubyte blue), red, green, blue)
+DEF_GLX_PROTO(void, glColor3ui,(GLuint red, GLuint green, GLuint blue), red, green, blue)
+DEF_GLX_PROTO(void, glColor3us,(GLushort red, GLushort green, GLushort blue), red, green, blue)
+DEF_GLX_PROTO(void, glColor4b,(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glColor4d,(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glColor4f,(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glColor4i,(GLint red, GLint green, GLint blue, GLint alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glColor4s,(GLshort red, GLshort green, GLshort blue, GLshort alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glColor4ub,(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glColor4ui,(GLuint red, GLuint green, GLuint blue, GLuint alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glColor4us,(GLushort red, GLushort green, GLushort blue, GLushort alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glColor3bv,(const GLbyte *v), v)
+DEF_GLX_PROTO(void, glColor3dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glColor3fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glColor3iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glColor3sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glColor3ubv,(const GLubyte *v), v)
+DEF_GLX_PROTO(void, glColor3uiv,(const GLuint *v), v)
+DEF_GLX_PROTO(void, glColor3usv,(const GLushort *v), v)
+DEF_GLX_PROTO(void, glColor4bv,(const GLbyte *v), v)
+DEF_GLX_PROTO(void, glColor4dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glColor4fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glColor4iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glColor4sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glColor4ubv,(const GLubyte *v), v)
+DEF_GLX_PROTO(void, glColor4uiv,(const GLuint *v), v)
+DEF_GLX_PROTO(void, glColor4usv,(const GLushort *v), v)
+DEF_GLX_PROTO(void, glTexCoord1d,(GLdouble s), s)
+DEF_GLX_PROTO(void, glTexCoord1f,(GLfloat s), s)
+DEF_GLX_PROTO(void, glTexCoord1i,(GLint s), s)
+DEF_GLX_PROTO(void, glTexCoord1s,(GLshort s), s)
+DEF_GLX_PROTO(void, glTexCoord2d,(GLdouble s, GLdouble t), s, t)
+DEF_GLX_PROTO(void, glTexCoord2f,(GLfloat s, GLfloat t), s, t)
+DEF_GLX_PROTO(void, glTexCoord2i,(GLint s, GLint t), s, t)
+DEF_GLX_PROTO(void, glTexCoord2s,(GLshort s, GLshort t), s, t)
+DEF_GLX_PROTO(void, glTexCoord3d,(GLdouble s, GLdouble t, GLdouble r), s, t, r)
+DEF_GLX_PROTO(void, glTexCoord3f,(GLfloat s, GLfloat t, GLfloat r), s, t, r)
+DEF_GLX_PROTO(void, glTexCoord3i,(GLint s, GLint t, GLint r), s, t, r)
+DEF_GLX_PROTO(void, glTexCoord3s,(GLshort s, GLshort t, GLshort r), s, t, r)
+DEF_GLX_PROTO(void, glTexCoord4d,(GLdouble s, GLdouble t, GLdouble r, GLdouble q), s, t, r, q)
+DEF_GLX_PROTO(void, glTexCoord4f,(GLfloat s, GLfloat t, GLfloat r, GLfloat q), s, t, r, q)
+DEF_GLX_PROTO(void, glTexCoord4i,(GLint s, GLint t, GLint r, GLint q), s, t, r, q)
+DEF_GLX_PROTO(void, glTexCoord4s,(GLshort s, GLshort t, GLshort r, GLshort q), s, t, r, q)
+DEF_GLX_PROTO(void, glTexCoord1dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glTexCoord1fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glTexCoord1iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glTexCoord1sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glTexCoord2dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glTexCoord2fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glTexCoord2iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glTexCoord2sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glTexCoord3dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glTexCoord3fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glTexCoord3iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glTexCoord3sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glTexCoord4dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glTexCoord4fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glTexCoord4iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glTexCoord4sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glRasterPos2d,(GLdouble x, GLdouble y), x, y)
+DEF_GLX_PROTO(void, glRasterPos2f,(GLfloat x, GLfloat y), x, y)
+DEF_GLX_PROTO(void, glRasterPos2i,(GLint x, GLint y), x, y)
+DEF_GLX_PROTO(void, glRasterPos2s,(GLshort x, GLshort y), x, y)
+DEF_GLX_PROTO(void, glRasterPos3d,(GLdouble x, GLdouble y, GLdouble z), x, y, z)
+DEF_GLX_PROTO(void, glRasterPos3f,(GLfloat x, GLfloat y, GLfloat z), x, y, z)
+DEF_GLX_PROTO(void, glRasterPos3i,(GLint x, GLint y, GLint z), x, y, z)
+DEF_GLX_PROTO(void, glRasterPos3s,(GLshort x, GLshort y, GLshort z), x, y, z)
+DEF_GLX_PROTO(void, glRasterPos4d,(GLdouble x, GLdouble y, GLdouble z, GLdouble w), x, y, z, w)
+DEF_GLX_PROTO(void, glRasterPos4f,(GLfloat x, GLfloat y, GLfloat z, GLfloat w), x, y, z, w)
+DEF_GLX_PROTO(void, glRasterPos4i,(GLint x, GLint y, GLint z, GLint w), x, y, z, w)
+DEF_GLX_PROTO(void, glRasterPos4s,(GLshort x, GLshort y, GLshort z, GLshort w), x, y, z, w)
+DEF_GLX_PROTO(void, glRasterPos2dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glRasterPos2fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glRasterPos2iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glRasterPos2sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glRasterPos3dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glRasterPos3fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glRasterPos3iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glRasterPos3sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glRasterPos4dv,(const GLdouble *v), v)
+DEF_GLX_PROTO(void, glRasterPos4fv,(const GLfloat *v), v)
+DEF_GLX_PROTO(void, glRasterPos4iv,(const GLint *v), v)
+DEF_GLX_PROTO(void, glRasterPos4sv,(const GLshort *v), v)
+DEF_GLX_PROTO(void, glRectd,(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2), x1, y1, x2, y2)
+DEF_GLX_PROTO(void, glRectf,(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2), x1, y1, x2, y2)
+DEF_GLX_PROTO(void, glRecti,(GLint x1, GLint y1, GLint x2, GLint y2), x1, y1, x2, y2)
+DEF_GLX_PROTO(void, glRects,(GLshort x1, GLshort y1, GLshort x2, GLshort y2), x1, y1, x2, y2)
+DEF_GLX_PROTO(void, glRectdv,(const GLdouble *v1, const GLdouble *v2), v1, v2)
+DEF_GLX_PROTO(void, glRectfv,(const GLfloat *v1, const GLfloat *v2), v1, v2)
+DEF_GLX_PROTO(void, glRectiv,(const GLint *v1, const GLint *v2), v1, v2)
+DEF_GLX_PROTO(void, glRectsv,(const GLshort *v1, const GLshort *v2), v1, v2)
+DEF_GLX_PROTO(void, glVertexPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr), size, type, stride, ptr)
+DEF_GLX_PROTO(void, glNormalPointer,(GLenum type, GLsizei stride, const GLvoid *ptr), type, stride, ptr)
+DEF_GLX_PROTO(void, glColorPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr), size, type, stride, ptr)
+DEF_GLX_PROTO(void, glIndexPointer,(GLenum type, GLsizei stride, const GLvoid *ptr), type, stride, ptr)
+DEF_GLX_PROTO(void, glTexCoordPointer,(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr), size, type, stride, ptr)
+DEF_GLX_PROTO(void, glEdgeFlagPointer,(GLsizei stride, const GLvoid *ptr), stride, ptr)
+DEF_GLX_PROTO(void, glGetPointerv,(GLenum pname, GLvoid **params), pname, params)
+DEF_GLX_PROTO(void, glArrayElement,(GLint i), i)
+DEF_GLX_PROTO(void, glDrawArrays,(GLenum mode, GLint first, GLsizei count), mode, first, count)
+DEF_GLX_PROTO(void, glDrawElements,(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices), mode, count, type, indices)
+DEF_GLX_PROTO(void, glInterleavedArrays,(GLenum format, GLsizei stride, const GLvoid *pointer), format, stride, pointer)
+DEF_GLX_PROTO(void, glShadeModel,(GLenum mode), mode)
+DEF_GLX_PROTO(void, glLightf,(GLenum light, GLenum pname, GLfloat param), light, pname, param)
+DEF_GLX_PROTO(void, glLighti,(GLenum light, GLenum pname, GLint param), light, pname, param)
+DEF_GLX_PROTO(void, glLightfv,(GLenum light, GLenum pname, const GLfloat *params), light, pname, params)
+DEF_GLX_PROTO(void, glLightiv,(GLenum light, GLenum pname, const GLint *params), light, pname, params)
+DEF_GLX_PROTO(void, glGetLightfv,(GLenum light, GLenum pname, GLfloat *params), light, pname, params)
+DEF_GLX_PROTO(void, glGetLightiv,(GLenum light, GLenum pname, GLint *params), light, pname, params)
+DEF_GLX_PROTO(void, glLightModelf,(GLenum pname, GLfloat param), pname, param)
+DEF_GLX_PROTO(void, glLightModeli,(GLenum pname, GLint param), pname, param)
+DEF_GLX_PROTO(void, glLightModelfv,(GLenum pname, const GLfloat *params), pname, params)
+DEF_GLX_PROTO(void, glLightModeliv,(GLenum pname, const GLint *params), pname, params)
+DEF_GLX_PROTO(void, glMaterialf,(GLenum face, GLenum pname, GLfloat param), face, pname, param)
+DEF_GLX_PROTO(void, glMateriali,(GLenum face, GLenum pname, GLint param), face, pname, param)
+DEF_GLX_PROTO(void, glMaterialfv,(GLenum face, GLenum pname, const GLfloat *params), face, pname, params)
+DEF_GLX_PROTO(void, glMaterialiv,(GLenum face, GLenum pname, const GLint *params), face, pname, params)
+DEF_GLX_PROTO(void, glGetMaterialfv,(GLenum face, GLenum pname, GLfloat *params), face, pname, params)
+DEF_GLX_PROTO(void, glGetMaterialiv,(GLenum face, GLenum pname, GLint *params), face, pname, params)
+DEF_GLX_PROTO(void, glColorMaterial,(GLenum face, GLenum mode), face, mode)
+DEF_GLX_PROTO(void, glPixelZoom,(GLfloat xfactor, GLfloat yfactor), xfactor, yfactor)
+DEF_GLX_PROTO(void, glPixelStoref,(GLenum pname, GLfloat param), pname, param)
+DEF_GLX_PROTO(void, glPixelStorei,(GLenum pname, GLint param), pname, param)
+DEF_GLX_PROTO(void, glPixelTransferf,(GLenum pname, GLfloat param), pname, param)
+DEF_GLX_PROTO(void, glPixelTransferi,(GLenum pname, GLint param), pname, param)
+DEF_GLX_PROTO(void, glPixelMapfv,(GLenum map, GLsizei mapsize, const GLfloat *values), map, mapsize, values)
+DEF_GLX_PROTO(void, glPixelMapuiv,(GLenum map, GLsizei mapsize, const GLuint *values), map, mapsize, values)
+DEF_GLX_PROTO(void, glPixelMapusv,(GLenum map, GLsizei mapsize, const GLushort *values), map, mapsize, values)
+DEF_GLX_PROTO(void, glGetPixelMapfv,(GLenum map, GLfloat *values), map, values)
+DEF_GLX_PROTO(void, glGetPixelMapuiv,(GLenum map, GLuint *values), map, values)
+DEF_GLX_PROTO(void, glGetPixelMapusv,(GLenum map, GLushort *values), map, values)
+DEF_GLX_PROTO(void, glBitmap,(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap), width, height, xorig, yorig, xmove, ymove, bitmap)
+DEF_GLX_PROTO(void, glReadPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels), x, y, width, height, format, type, pixels)
+DEF_GLX_PROTO(void, glDrawPixels,(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels), width, height, format, type, pixels)
+DEF_GLX_PROTO(void, glCopyPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type), x, y, width, height, type)
+DEF_GLX_PROTO(void, glStencilFunc,(GLenum func, GLint ref, GLuint mask), func, ref, mask)
+DEF_GLX_PROTO(void, glStencilMask,(GLuint mask), mask)
+DEF_GLX_PROTO(void, glStencilOp,(GLenum fail, GLenum zfail, GLenum zpass), fail, zfail, zpass)
+DEF_GLX_PROTO(void, glClearStencil,(GLint s), s)
+DEF_GLX_PROTO(void, glTexGend,(GLenum coord, GLenum pname, GLdouble param), coord, pname, param)
+DEF_GLX_PROTO(void, glTexGenf,(GLenum coord, GLenum pname, GLfloat param), coord, pname, param)
+DEF_GLX_PROTO(void, glTexGeni,(GLenum coord, GLenum pname, GLint param), coord, pname, param)
+DEF_GLX_PROTO(void, glTexGendv,(GLenum coord, GLenum pname, const GLdouble *params), coord, pname, params)
+DEF_GLX_PROTO(void, glTexGenfv,(GLenum coord, GLenum pname, const GLfloat *params), coord, pname, params)
+DEF_GLX_PROTO(void, glTexGeniv,(GLenum coord, GLenum pname, const GLint *params), coord, pname, params)
+DEF_GLX_PROTO(void, glGetTexGendv,(GLenum coord, GLenum pname, GLdouble *params), coord, pname, params)
+DEF_GLX_PROTO(void, glGetTexGenfv,(GLenum coord, GLenum pname, GLfloat *params), coord, pname, params)
+DEF_GLX_PROTO(void, glGetTexGeniv,(GLenum coord, GLenum pname, GLint *params), coord, pname, params)
+DEF_GLX_PROTO(void, glTexEnvf,(GLenum target, GLenum pname, GLfloat param), target, pname, param)
+DEF_GLX_PROTO(void, glTexEnvi,(GLenum target, GLenum pname, GLint param), target, pname, param)
+DEF_GLX_PROTO(void, glTexEnvfv,(GLenum target, GLenum pname, const GLfloat *params), target, pname, params)
+DEF_GLX_PROTO(void, glTexEnviv,(GLenum target, GLenum pname, const GLint *params), target, pname, params)
+DEF_GLX_PROTO(void, glGetTexEnvfv,(GLenum target, GLenum pname, GLfloat *params), target, pname, params)
+DEF_GLX_PROTO(void, glGetTexEnviv,(GLenum target, GLenum pname, GLint *params), target, pname, params)
+DEF_GLX_PROTO(void, glTexParameterf,(GLenum target, GLenum pname, GLfloat param), target, pname, param)
+DEF_GLX_PROTO(void, glTexParameteri,(GLenum target, GLenum pname, GLint param), target, pname, param)
+DEF_GLX_PROTO(void, glTexParameterfv,(GLenum target, GLenum pname, const GLfloat *params), target, pname, params)
+DEF_GLX_PROTO(void, glTexParameteriv,(GLenum target, GLenum pname, const GLint *params), target, pname, params)
+DEF_GLX_PROTO(void, glGetTexParameterfv,(GLenum target, GLenum pname, GLfloat *params), target, pname, params)
+DEF_GLX_PROTO(void, glGetTexParameteriv,(GLenum target, GLenum pname, GLint *params), target, pname, params)
+DEF_GLX_PROTO(void, glGetTexLevelParameterfv,(GLenum target, GLint level, GLenum pname, GLfloat *params), target, level, pname, params)
+DEF_GLX_PROTO(void, glGetTexLevelParameteriv,(GLenum target, GLint level, GLenum pname, GLint *params), target, level, pname, params)
+DEF_GLX_PROTO(void, glTexImage1D,(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels), target, level, internalFormat, width, border, format, type, pixels)
+DEF_GLX_PROTO(void, glTexImage2D,(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels), target, level, internalFormat, width, height, border, format, type, pixels)
+DEF_GLX_PROTO(void, glGetTexImage,(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels), target, level, format, type, pixels)
+DEF_GLX_PROTO(void, glGenTextures,(GLsizei n, GLuint *textures), n, textures)
+DEF_GLX_PROTO(void, glDeleteTextures,(GLsizei n, const GLuint *textures), n, textures)
+DEF_GLX_PROTO(void, glBindTexture,(GLenum target, GLuint texture), target, texture)
+DEF_GLX_PROTO(void, glPrioritizeTextures,(GLsizei n, const GLuint *textures, const GLclampf *priorities), n, textures, priorities)
+DEF_GLX_PROTO(GLboolean, glAreTexturesResident,(GLsizei n, const GLuint *textures, GLboolean *residences), n, textures, residences)
+DEF_GLX_PROTO(GLboolean, glIsTexture,(GLuint texture), texture)
+DEF_GLX_PROTO(void, glTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels), target, level, xoffset, width, format, type, pixels)
+DEF_GLX_PROTO(void, glTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels), target, level, xoffset, yoffset, width, height, format, type, pixels)
+DEF_GLX_PROTO(void, glCopyTexImage1D,(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border), target, level, internalformat, x, y, width, border)
+DEF_GLX_PROTO(void, glCopyTexImage2D,(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border), target, level, internalformat, x, y, width, height, border)
+DEF_GLX_PROTO(void, glCopyTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width), target, level, xoffset, x, y, width)
+DEF_GLX_PROTO(void, glCopyTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height), target, level, xoffset, yoffset, x, y, width, height)
+DEF_GLX_PROTO(void, glMap1d,(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points), target, u1, u2, stride, order, points)
+DEF_GLX_PROTO(void, glMap1f,(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points), target, u1, u2, stride, order, points)
+DEF_GLX_PROTO(void, glMap2d,(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points), target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points)
+DEF_GLX_PROTO(void, glMap2f,(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points), target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points)
+DEF_GLX_PROTO(void, glGetMapdv,(GLenum target, GLenum query, GLdouble *v), target, query, v)
+DEF_GLX_PROTO(void, glGetMapfv,(GLenum target, GLenum query, GLfloat *v), target, query, v)
+DEF_GLX_PROTO(void, glGetMapiv,(GLenum target, GLenum query, GLint *v), target, query, v)
+DEF_GLX_PROTO(void, glEvalCoord1d,(GLdouble u), u)
+DEF_GLX_PROTO(void, glEvalCoord1f,(GLfloat u), u)
+DEF_GLX_PROTO(void, glEvalCoord1dv,(const GLdouble *u), u)
+DEF_GLX_PROTO(void, glEvalCoord1fv,(const GLfloat *u), u)
+DEF_GLX_PROTO(void, glEvalCoord2d,(GLdouble u, GLdouble v), u, v)
+DEF_GLX_PROTO(void, glEvalCoord2f,(GLfloat u, GLfloat v), u, v)
+DEF_GLX_PROTO(void, glEvalCoord2dv,(const GLdouble *u), u)
+DEF_GLX_PROTO(void, glEvalCoord2fv,(const GLfloat *u), u)
+DEF_GLX_PROTO(void, glMapGrid1d,(GLint un, GLdouble u1, GLdouble u2), un, u1, u2)
+DEF_GLX_PROTO(void, glMapGrid1f,(GLint un, GLfloat u1, GLfloat u2), un, u1, u2)
+DEF_GLX_PROTO(void, glMapGrid2d,(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2), un, u1, u2, vn, v1, v2)
+DEF_GLX_PROTO(void, glMapGrid2f,(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2), un, u1, u2, vn, v1, v2)
+DEF_GLX_PROTO(void, glEvalPoint1,(GLint i), i)
+DEF_GLX_PROTO(void, glEvalPoint2,(GLint i, GLint j), i, j)
+DEF_GLX_PROTO(void, glEvalMesh1,(GLenum mode, GLint i1, GLint i2), mode, i1, i2)
+DEF_GLX_PROTO(void, glEvalMesh2,(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2), mode, i1, i2, j1, j2)
+DEF_GLX_PROTO(void, glFogf,(GLenum pname, GLfloat param), pname, param)
+DEF_GLX_PROTO(void, glFogi,(GLenum pname, GLint param), pname, param)
+DEF_GLX_PROTO(void, glFogfv,(GLenum pname, const GLfloat *params), pname, params)
+DEF_GLX_PROTO(void, glFogiv,(GLenum pname, const GLint *params), pname, params)
+DEF_GLX_PROTO(void, glFeedbackBuffer,(GLsizei size, GLenum type, GLfloat *buffer), size, type, buffer)
+DEF_GLX_PROTO(void, glPassThrough,(GLfloat token), token)
+DEF_GLX_PROTO(void, glSelectBuffer,(GLsizei size, GLuint *buffer), size, buffer)
+DEF_GLX_PROTO(void, glInitNames,(void))
+DEF_GLX_PROTO(void, glLoadName,(GLuint name), name)
+DEF_GLX_PROTO(void, glPushName,(GLuint name), name)
+DEF_GLX_PROTO(void, glPopName,(void))
+DEF_GLX_PROTO(void, glDrawRangeElements,(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices), mode, start, end, count, type, indices)
+DEF_GLX_PROTO(void, glTexImage3D,(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels), target, level, internalFormat, width, height, depth, border, format, type, pixels)
+DEF_GLX_PROTO(void, glTexSubImage3D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels), target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels)
+DEF_GLX_PROTO(void, glCopyTexSubImage3D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height), target, level, xoffset, yoffset, zoffset, x, y, width, height)
+DEF_GLX_PROTO(void, glColorTable,(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table), target, internalformat, width, format, type, table)
+DEF_GLX_PROTO(void, glColorSubTable,(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data), target, start, count, format, type, data)
+DEF_GLX_PROTO(void, glColorTableParameteriv,(GLenum target, GLenum pname, const GLint *params), target, pname, params)
+DEF_GLX_PROTO(void, glColorTableParameterfv,(GLenum target, GLenum pname, const GLfloat *params), target, pname, params)
+DEF_GLX_PROTO(void, glCopyColorSubTable,(GLenum target, GLsizei start, GLint x, GLint y, GLsizei width), target, start, x, y, width)
+DEF_GLX_PROTO(void, glCopyColorTable,(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width), target, internalformat, x, y, width)
+DEF_GLX_PROTO(void, glGetColorTable,(GLenum target, GLenum format, GLenum type, GLvoid *table), target, format, type, table)
+DEF_GLX_PROTO(void, glGetColorTableParameterfv,(GLenum target, GLenum pname, GLfloat *params), target, pname, params)
+DEF_GLX_PROTO(void, glGetColorTableParameteriv,(GLenum target, GLenum pname, GLint *params), target, pname, params)
+DEF_GLX_PROTO(void, glBlendEquation,(GLenum mode), mode)
+DEF_GLX_PROTO(void, glBlendColor,(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha), red, green, blue, alpha)
+DEF_GLX_PROTO(void, glHistogram,(GLenum target, GLsizei width, GLenum internalformat, GLboolean sink), target, width, internalformat, sink)
+DEF_GLX_PROTO(void, glResetHistogram,(GLenum target), target)
+DEF_GLX_PROTO(void, glGetHistogram,(GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values), target, reset, format, type, values)
+DEF_GLX_PROTO(void, glGetHistogramParameterfv,(GLenum target, GLenum pname, GLfloat *params), target, pname, params)
+DEF_GLX_PROTO(void, glGetHistogramParameteriv,(GLenum target, GLenum pname, GLint *params), target, pname, params)
+DEF_GLX_PROTO(void, glMinmax,(GLenum target, GLenum internalformat, GLboolean sink), target, internalformat, sink)
+DEF_GLX_PROTO(void, glResetMinmax,(GLenum target), target)
+DEF_GLX_PROTO(void, glGetMinmax,(GLenum target, GLboolean reset, GLenum format, GLenum types, GLvoid *values), target, reset, format, types, values)
+DEF_GLX_PROTO(void, glGetMinmaxParameterfv,(GLenum target, GLenum pname, GLfloat *params), target, pname, params)
+DEF_GLX_PROTO(void, glGetMinmaxParameteriv,(GLenum target, GLenum pname, GLint *params), target, pname, params)
+DEF_GLX_PROTO(void, glConvolutionFilter1D,(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image), target, internalformat, width, format, type, image)
+DEF_GLX_PROTO(void, glConvolutionFilter2D,(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image), target, internalformat, width, height, format, type, image)
+DEF_GLX_PROTO(void, glConvolutionParameterf,(GLenum target, GLenum pname, GLfloat params), target, pname, params)
+DEF_GLX_PROTO(void, glConvolutionParameterfv,(GLenum target, GLenum pname, const GLfloat *params), target, pname, params)
+DEF_GLX_PROTO(void, glConvolutionParameteri,(GLenum target, GLenum pname, GLint params), target, pname, params)
+DEF_GLX_PROTO(void, glConvolutionParameteriv,(GLenum target, GLenum pname, const GLint *params), target, pname, params)
+DEF_GLX_PROTO(void, glCopyConvolutionFilter1D,(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width), target, internalformat, x, y, width)
+DEF_GLX_PROTO(void, glCopyConvolutionFilter2D,(GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height), target, internalformat, x, y, width, height)
+DEF_GLX_PROTO(void, glGetConvolutionFilter,(GLenum target, GLenum format, GLenum type, GLvoid *image), target, format, type, image)
+DEF_GLX_PROTO(void, glGetConvolutionParameterfv,(GLenum target, GLenum pname, GLfloat *params), target, pname, params)
+DEF_GLX_PROTO(void, glGetConvolutionParameteriv,(GLenum target, GLenum pname, GLint *params), target, pname, params)
+DEF_GLX_PROTO(void, glSeparableFilter2D,(GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column), target, internalformat, width, height, format, type, row, column)
+DEF_GLX_PROTO(void, glGetSeparableFilter,(GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span), target, format, type, row, column, span)
+DEF_GLX_PROTO(void, glActiveTexture,(GLenum texture), texture)
+DEF_GLX_PROTO(void, glClientActiveTexture,(GLenum texture), texture)
+DEF_GLX_PROTO(void, glCompressedTexImage1D,(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data), target, level, internalformat, width, border, imageSize, data)
+DEF_GLX_PROTO(void, glCompressedTexImage2D,(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data), target, level, internalformat, width, height, border, imageSize, data)
+DEF_GLX_PROTO(void, glCompressedTexImage3D,(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data), target, level, internalformat, width, height, depth, border, imageSize, data)
+DEF_GLX_PROTO(void, glCompressedTexSubImage1D,(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data), target, level, xoffset, width, format, imageSize, data)
+DEF_GLX_PROTO(void, glCompressedTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data), target, level, xoffset, yoffset, width, height, format, imageSize, data)
+DEF_GLX_PROTO(void, glCompressedTexSubImage3D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data), target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data)
+DEF_GLX_PROTO(void, glGetCompressedTexImage,(GLenum target, GLint lod, GLvoid *img), target, lod, img)
+DEF_GLX_PROTO(void, glMultiTexCoord1d,(GLenum target, GLdouble s), target, s)
+DEF_GLX_PROTO(void, glMultiTexCoord1dv,(GLenum target, const GLdouble *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord1f,(GLenum target, GLfloat s), target, s)
+DEF_GLX_PROTO(void, glMultiTexCoord1fv,(GLenum target, const GLfloat *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord1i,(GLenum target, GLint s), target, s)
+DEF_GLX_PROTO(void, glMultiTexCoord1iv,(GLenum target, const GLint *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord1s,(GLenum target, GLshort s), target, s)
+DEF_GLX_PROTO(void, glMultiTexCoord1sv,(GLenum target, const GLshort *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord2d,(GLenum target, GLdouble s, GLdouble t), target, s, t)
+DEF_GLX_PROTO(void, glMultiTexCoord2dv,(GLenum target, const GLdouble *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord2f,(GLenum target, GLfloat s, GLfloat t), target, s, t)
+DEF_GLX_PROTO(void, glMultiTexCoord2fv,(GLenum target, const GLfloat *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord2i,(GLenum target, GLint s, GLint t), target, s, t)
+DEF_GLX_PROTO(void, glMultiTexCoord2iv,(GLenum target, const GLint *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord2s,(GLenum target, GLshort s, GLshort t), target, s, t)
+DEF_GLX_PROTO(void, glMultiTexCoord2sv,(GLenum target, const GLshort *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord3d,(GLenum target, GLdouble s, GLdouble t, GLdouble r), target, s, t, r)
+DEF_GLX_PROTO(void, glMultiTexCoord3dv,(GLenum target, const GLdouble *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord3f,(GLenum target, GLfloat s, GLfloat t, GLfloat r), target, s, t, r)
+DEF_GLX_PROTO(void, glMultiTexCoord3fv,(GLenum target, const GLfloat *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord3i,(GLenum target, GLint s, GLint t, GLint r), target, s, t, r)
+DEF_GLX_PROTO(void, glMultiTexCoord3iv,(GLenum target, const GLint *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord3s,(GLenum target, GLshort s, GLshort t, GLshort r), target, s, t, r)
+DEF_GLX_PROTO(void, glMultiTexCoord3sv,(GLenum target, const GLshort *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord4d,(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q), target, s, t, r, q)
+DEF_GLX_PROTO(void, glMultiTexCoord4dv,(GLenum target, const GLdouble *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord4f,(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q), target, s, t, r, q)
+DEF_GLX_PROTO(void, glMultiTexCoord4fv,(GLenum target, const GLfloat *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord4i,(GLenum target, GLint s, GLint t, GLint r, GLint q), target, s, t, r, q)
+DEF_GLX_PROTO(void, glMultiTexCoord4iv,(GLenum target, const GLint *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord4s,(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q), target, s, t, r, q)
+DEF_GLX_PROTO(void, glMultiTexCoord4sv,(GLenum target, const GLshort *v), target, v)
+DEF_GLX_PROTO(void, glLoadTransposeMatrixd,(const GLdouble m[16]), m)
+DEF_GLX_PROTO(void, glLoadTransposeMatrixf,(const GLfloat m[16]), m)
+DEF_GLX_PROTO(void, glMultTransposeMatrixd,(const GLdouble m[16]), m)
+DEF_GLX_PROTO(void, glMultTransposeMatrixf,(const GLfloat m[16]), m)
+DEF_GLX_PROTO(void, glSampleCoverage,(GLclampf value, GLboolean invert), value, invert)
+DEF_GLX_PROTO(void, glActiveTextureARB,(GLenum texture), texture)
+DEF_GLX_PROTO(void, glClientActiveTextureARB,(GLenum texture), texture)
+DEF_GLX_PROTO(void, glMultiTexCoord1dARB,(GLenum target, GLdouble s), target, s)
+DEF_GLX_PROTO(void, glMultiTexCoord1dvARB,(GLenum target, const GLdouble *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord1fARB,(GLenum target, GLfloat s), target, s)
+DEF_GLX_PROTO(void, glMultiTexCoord1fvARB,(GLenum target, const GLfloat *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord1iARB,(GLenum target, GLint s), target, s)
+DEF_GLX_PROTO(void, glMultiTexCoord1ivARB,(GLenum target, const GLint *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord1sARB,(GLenum target, GLshort s), target, s)
+DEF_GLX_PROTO(void, glMultiTexCoord1svARB,(GLenum target, const GLshort *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord2dARB,(GLenum target, GLdouble s, GLdouble t), target, s, t)
+DEF_GLX_PROTO(void, glMultiTexCoord2dvARB,(GLenum target, const GLdouble *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord2fARB,(GLenum target, GLfloat s, GLfloat t), target, s, t)
+DEF_GLX_PROTO(void, glMultiTexCoord2fvARB,(GLenum target, const GLfloat *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord2iARB,(GLenum target, GLint s, GLint t), target, s, t)
+DEF_GLX_PROTO(void, glMultiTexCoord2ivARB,(GLenum target, const GLint *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord2sARB,(GLenum target, GLshort s, GLshort t), target, s, t)
+DEF_GLX_PROTO(void, glMultiTexCoord2svARB,(GLenum target, const GLshort *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord3dARB,(GLenum target, GLdouble s, GLdouble t, GLdouble r), target, s, t, r)
+DEF_GLX_PROTO(void, glMultiTexCoord3dvARB,(GLenum target, const GLdouble *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord3fARB,(GLenum target, GLfloat s, GLfloat t, GLfloat r), target, s, t, r)
+DEF_GLX_PROTO(void, glMultiTexCoord3fvARB,(GLenum target, const GLfloat *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord3iARB,(GLenum target, GLint s, GLint t, GLint r), target, s, t, r)
+DEF_GLX_PROTO(void, glMultiTexCoord3ivARB,(GLenum target, const GLint *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord3sARB,(GLenum target, GLshort s, GLshort t, GLshort r), target, s, t, r)
+DEF_GLX_PROTO(void, glMultiTexCoord3svARB,(GLenum target, const GLshort *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord4dARB,(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q), target, s, t, r, q)
+DEF_GLX_PROTO(void, glMultiTexCoord4dvARB,(GLenum target, const GLdouble *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord4fARB,(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q), target, s, t, r, q)
+DEF_GLX_PROTO(void, glMultiTexCoord4fvARB,(GLenum target, const GLfloat *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord4iARB,(GLenum target, GLint s, GLint t, GLint r, GLint q), target, s, t, r, q)
+DEF_GLX_PROTO(void, glMultiTexCoord4ivARB,(GLenum target, const GLint *v), target, v)
+DEF_GLX_PROTO(void, glMultiTexCoord4sARB,(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q), target, s, t, r, q)
+DEF_GLX_PROTO(void, glMultiTexCoord4svARB,(GLenum target, const GLshort *v), target, v)
diff --git a/glext-passthru.def b/glext-passthru.def
new file mode 100644 (file)
index 0000000..2b7fba5
--- /dev/null
@@ -0,0 +1,803 @@
+P(glActiveProgramEXT)
+P(glAlphaFragmentOp1ATI)
+P(glAlphaFragmentOp2ATI)
+P(glAlphaFragmentOp3ATI)
+P(glAreProgramsResidentNV)
+P(glAreTexturesResidentEXT)
+P(glArrayElementEXT)
+P(glAttachObjectARB)
+P(glAttachShader)
+P(glBeginConditionalRender)
+P(glBeginConditionalRenderNV)
+P(glBeginFragmentShaderATI)
+P(glBeginQuery)
+P(glBeginQueryARB)
+P(glBeginQueryIndexed)
+P(glBeginTransformFeedback)
+P(glBeginTransformFeedbackEXT)
+P(glBindAttribLocation)
+P(glBindAttribLocationARB)
+P(glBindBuffer)
+P(glBindBufferARB)
+P(glBindBufferBase)
+P(glBindBufferBaseEXT)
+P(glBindBufferOffsetEXT)
+P(glBindBufferRange)
+P(glBindBufferRangeEXT)
+P(glBindFragDataLocation)
+P(glBindFragDataLocationEXT)
+P(glBindFragDataLocationIndexed)
+P(glBindFragmentShaderATI)
+P(glBindFramebuffer)
+P(glBindFramebufferEXT)
+P(glBindProgramARB)
+P(glBindProgramNV)
+P(glBindRenderbuffer)
+P(glBindRenderbufferEXT)
+P(glBindSampler)
+P(glBindTextureEXT)
+P(glBindTransformFeedback)
+P(glBindVertexArray)
+P(glBindVertexArrayOES)
+P(glBlendColorEXT)
+P(glBlendEquationEXT)
+P(glBlendEquationIndexedAMD)
+P(glBlendEquationSeparate)
+P(glBlendEquationSeparateIndexedAMD)
+P(glBlendEquationSeparateiARB)
+P(glBlendEquationiARB)
+P(glBlendFuncIndexedAMD)
+P(glBlendFuncSeparate)
+P(glBlendFuncSeparateEXT)
+P(glBlendFuncSeparateIndexedAMD)
+P(glBlendFuncSeparateiARB)
+P(glBlendFunciARB)
+P(glBlitFramebuffer)
+P(glBufferData)
+P(glBufferDataARB)
+P(glBufferSubData)
+P(glBufferSubDataARB)
+P(glCheckFramebufferStatus)
+P(glCheckFramebufferStatusEXT)
+P(glClampColor)
+P(glClampColorARB)
+P(glClearBufferfi)
+P(glClearBufferfv)
+P(glClearBufferiv)
+P(glClearBufferuiv)
+P(glClearColorIiEXT)
+P(glClearColorIuiEXT)
+P(glClearDepthf)
+P(glClientWaitSync)
+P(glColorFragmentOp1ATI)
+P(glColorFragmentOp2ATI)
+P(glColorFragmentOp3ATI)
+P(glColorMaskIndexedEXT)
+P(glColorMaski)
+P(glColorP3ui)
+P(glColorP3uiv)
+P(glColorP4ui)
+P(glColorP4uiv)
+P(glColorPointerEXT)
+P(glColorTableEXT)
+P(glCompileShader)
+P(glCompileShaderARB)
+P(glCompressedTexImage1DARB)
+P(glCompressedTexImage2DARB)
+P(glCompressedTexImage3DARB)
+P(glCompressedTexSubImage1DARB)
+P(glCompressedTexSubImage2DARB)
+P(glCompressedTexSubImage3DARB)
+P(glCopyBufferSubData)
+P(glCopyTexImage1DEXT)
+P(glCopyTexImage2DEXT)
+P(glCopyTexSubImage1DEXT)
+P(glCopyTexSubImage2DEXT)
+P(glCopyTexSubImage3DEXT)
+P(glCreateProgram)
+P(glCreateProgramObjectARB)
+P(glCreateShader)
+P(glCreateShaderObjectARB)
+P(glCreateShaderProgramEXT)
+P(glDebugMessageCallbackARB)
+P(glDebugMessageControlARB)
+P(glDebugMessageInsertARB)
+P(glDeleteBuffers)
+P(glDeleteBuffersARB)
+P(glDeleteFragmentShaderATI)
+P(glDeleteFramebuffers)
+P(glDeleteFramebuffersEXT)
+P(glDeleteObjectARB)
+P(glDeleteProgram)
+P(glDeleteProgramsARB)
+P(glDeleteProgramsNV)
+P(glDeleteQueries)
+P(glDeleteQueriesARB)
+P(glDeleteRenderbuffers)
+P(glDeleteRenderbuffersEXT)
+P(glDeleteSamplers)
+P(glDeleteShader)
+P(glDeleteSync)
+P(glDeleteTexturesEXT)
+P(glDeleteTransformFeedbacks)
+P(glDeleteVertexArrays)
+P(glDeleteVertexArraysOES)
+P(glDepthRangef)
+P(glDetachObjectARB)
+P(glDetachShader)
+P(glDisableIndexedEXT)
+P(glDisableVertexAttribArray)
+P(glDisableVertexAttribArrayARB)
+P(glDisablei)
+P(glDrawArraysEXT)
+P(glDrawArraysInstanced)
+P(glDrawArraysInstancedARB)
+P(glDrawArraysInstancedBaseInstance)
+P(glDrawArraysInstancedEXT)
+P(glDrawBuffers)
+P(glDrawBuffersARB)
+P(glDrawBuffersATI)
+P(glDrawBuffersNV)
+P(glDrawElementsBaseVertex)
+P(glDrawElementsInstanced)
+P(glDrawElementsInstancedARB)
+P(glDrawElementsInstancedBaseInstance)
+P(glDrawElementsInstancedBaseVertex)
+P(glDrawElementsInstancedBaseVertexBaseInstance)
+P(glDrawElementsInstancedEXT)
+P(glDrawRangeElementsBaseVertex)
+P(glDrawRangeElementsEXT)
+P(glDrawTransformFeedback)
+P(glDrawTransformFeedbackInstanced)
+P(glDrawTransformFeedbackStream)
+P(glDrawTransformFeedbackStreamInstanced)
+P(glEGLImageTargetRenderbufferStorageOES)
+P(glEGLImageTargetTexture2DOES)
+P(glEdgeFlagPointerEXT)
+P(glEnableIndexedEXT)
+P(glEnableVertexAttribArray)
+P(glEnableVertexAttribArrayARB)
+P(glEnablei)
+P(glEndConditionalRender)
+P(glEndConditionalRenderNV)
+P(glEndFragmentShaderATI)
+P(glEndQuery)
+P(glEndQueryARB)
+P(glEndQueryIndexed)
+P(glEndTransformFeedback)
+P(glEndTransformFeedbackEXT)
+P(glExecuteProgramNV)
+P(glFenceSync)
+P(glFlushMappedBufferRange)
+P(glFogCoordPointer)
+P(glFogCoordPointerEXT)
+P(glFogCoordd)
+P(glFogCoorddEXT)
+P(glFogCoorddv)
+P(glFogCoorddvEXT)
+P(glFogCoordf)
+P(glFogCoordfEXT)
+P(glFogCoordfv)
+P(glFogCoordfvEXT)
+P(glFramebufferRenderbuffer)
+P(glFramebufferRenderbufferEXT)
+P(glFramebufferTexture)
+P(glFramebufferTexture1D)
+P(glFramebufferTexture1DEXT)
+P(glFramebufferTexture2D)
+P(glFramebufferTexture2DEXT)
+P(glFramebufferTexture3D)
+P(glFramebufferTexture3DEXT)
+P(glFramebufferTextureARB)
+P(glFramebufferTextureFaceARB)
+P(glFramebufferTextureLayer)
+P(glFramebufferTextureLayerARB)
+P(glFramebufferTextureLayerEXT)
+P(glGenBuffers)
+P(glGenBuffersARB)
+P(glGenFragmentShadersATI)
+P(glGenFramebuffers)
+P(glGenFramebuffersEXT)
+P(glGenProgramsARB)
+P(glGenProgramsNV)
+P(glGenQueries)
+P(glGenQueriesARB)
+P(glGenRenderbuffers)
+P(glGenRenderbuffersEXT)
+P(glGenSamplers)
+P(glGenTexturesEXT)
+P(glGenTransformFeedbacks)
+P(glGenVertexArrays)
+P(glGenVertexArraysOES)
+P(glGenerateMipmap)
+P(glGenerateMipmapEXT)
+P(glGetActiveAttrib)
+P(glGetActiveAttribARB)
+P(glGetActiveUniform)
+P(glGetActiveUniformARB)
+P(glGetActiveUniformBlockName)
+P(glGetActiveUniformBlockiv)
+P(glGetActiveUniformName)
+P(glGetActiveUniformsiv)
+P(glGetAttachedObjectsARB)
+P(glGetAttachedShaders)
+P(glGetAttribLocation)
+P(glGetAttribLocationARB)
+P(glGetBooleanIndexedvEXT)
+P(glGetBooleani_v)
+P(glGetBufferParameteri64v)
+P(glGetBufferParameteriv)
+P(glGetBufferParameterivARB)
+P(glGetBufferPointerv)
+P(glGetBufferPointervARB)
+P(glGetBufferSubData)
+P(glGetBufferSubDataARB)
+P(glGetColorTableEXT)
+P(glGetColorTableParameterfvEXT)
+P(glGetColorTableParameterivEXT)
+P(glGetCompressedTexImageARB)
+P(glGetDebugMessageLogARB)
+P(glGetFragDataIndex)
+P(glGetFragDataLocation)
+P(glGetFragDataLocationEXT)
+P(glGetFramebufferAttachmentParameteriv)
+P(glGetFramebufferAttachmentParameterivEXT)
+P(glGetGraphicsResetStatusARB)
+P(glGetHandleARB)
+P(glGetInfoLogARB)
+P(glGetInteger64i_v)
+P(glGetInteger64v)
+P(glGetIntegerIndexedvEXT)
+P(glGetIntegeri_v)
+P(glGetObjectParameterfvARB)
+P(glGetObjectParameterivAPPLE)
+P(glGetObjectParameterivARB)
+P(glGetPointervEXT)
+P(glGetProgramEnvParameterdvARB)
+P(glGetProgramEnvParameterfvARB)
+P(glGetProgramInfoLog)
+P(glGetProgramLocalParameterdvARB)
+P(glGetProgramLocalParameterfvARB)
+P(glGetProgramNamedParameterdvNV)
+P(glGetProgramNamedParameterfvNV)
+P(glGetProgramParameterdvNV)
+P(glGetProgramParameterfvNV)
+P(glGetProgramStringARB)
+P(glGetProgramStringNV)
+P(glGetProgramiv)
+P(glGetProgramivARB)
+P(glGetProgramivNV)
+P(glGetQueryIndexediv)
+P(glGetQueryObjectiv)
+P(glGetQueryObjectivARB)
+P(glGetQueryObjectuiv)
+P(glGetQueryObjectuivARB)
+P(glGetQueryiv)
+P(glGetQueryivARB)
+P(glGetRenderbufferParameteriv)
+P(glGetRenderbufferParameterivEXT)
+P(glGetSamplerParameterIiv)
+P(glGetSamplerParameterIuiv)
+P(glGetSamplerParameterfv)
+P(glGetSamplerParameteriv)
+P(glGetShaderInfoLog)
+P(glGetShaderPrecisionFormat)
+P(glGetShaderSource)
+P(glGetShaderSourceARB)
+P(glGetShaderiv)
+P(glGetStringi)
+P(glGetSynciv)
+P(glGetTexBumpParameterfvATI)
+P(glGetTexBumpParameterivATI)
+P(glGetTexParameterIiv)
+P(glGetTexParameterIivEXT)
+P(glGetTexParameterIuiv)
+P(glGetTexParameterIuivEXT)
+P(glGetTrackMatrixivNV)
+P(glGetTransformFeedbackVarying)
+P(glGetTransformFeedbackVaryingEXT)
+P(glGetUniformBlockIndex)
+P(glGetUniformIndices)
+P(glGetUniformLocation)
+P(glGetUniformLocationARB)
+P(glGetUniformfv)
+P(glGetUniformfvARB)
+P(glGetUniformiv)
+P(glGetUniformivARB)
+P(glGetUniformuiv)
+P(glGetUniformuivEXT)
+P(glGetVertexAttribIiv)
+P(glGetVertexAttribIivEXT)
+P(glGetVertexAttribIuiv)
+P(glGetVertexAttribIuivEXT)
+P(glGetVertexAttribPointerv)
+P(glGetVertexAttribPointervARB)
+P(glGetVertexAttribPointervNV)
+P(glGetVertexAttribdv)
+P(glGetVertexAttribdvARB)
+P(glGetVertexAttribdvNV)
+P(glGetVertexAttribfv)
+P(glGetVertexAttribfvARB)
+P(glGetVertexAttribfvNV)
+P(glGetVertexAttribiv)
+P(glGetVertexAttribivARB)
+P(glGetVertexAttribivNV)
+P(glGetnColorTableARB)
+P(glGetnCompressedTexImageARB)
+P(glGetnConvolutionFilterARB)
+P(glGetnHistogramARB)
+P(glGetnMapdvARB)
+P(glGetnMapfvARB)
+P(glGetnMapivARB)
+P(glGetnMinmaxARB)
+P(glGetnPixelMapfvARB)
+P(glGetnPixelMapuivARB)
+P(glGetnPixelMapusvARB)
+P(glGetnPolygonStippleARB)
+P(glGetnSeparableFilterARB)
+P(glGetnTexImageARB)
+P(glGetnUniformdvARB)
+P(glGetnUniformfvARB)
+P(glGetnUniformivARB)
+P(glGetnUniformuivARB)
+P(glIndexPointerEXT)
+P(glInvalidateBufferData)
+P(glInvalidateBufferSubData)
+P(glInvalidateFramebuffer)
+P(glInvalidateSubFramebuffer)
+P(glInvalidateTexImage)
+P(glInvalidateTexSubImage)
+P(glIsBuffer)
+P(glIsBufferARB)
+P(glIsEnabledIndexedEXT)
+P(glIsEnabledi)
+P(glIsFramebuffer)
+P(glIsFramebufferEXT)
+P(glIsProgram)
+P(glIsProgramARB)
+P(glIsProgramNV)
+P(glIsQuery)
+P(glIsQueryARB)
+P(glIsRenderbuffer)
+P(glIsRenderbufferEXT)
+P(glIsSampler)
+P(glIsShader)
+P(glIsSync)
+P(glIsTextureEXT)
+P(glIsTransformFeedback)
+P(glIsVertexArray)
+P(glIsVertexArrayOES)
+P(glLinkProgram)
+P(glLinkProgramARB)
+P(glLoadProgramNV)
+P(glLoadTransposeMatrixdARB)
+P(glLoadTransposeMatrixfARB)
+P(glLockArraysEXT)
+P(glMapBuffer)
+P(glMapBufferARB)
+P(glMapBufferRange)
+P(glMultTransposeMatrixdARB)
+P(glMultTransposeMatrixfARB)
+P(glMultiDrawArrays)
+P(glMultiDrawArraysEXT)
+P(glMultiDrawElements)
+P(glMultiDrawElementsBaseVertex)
+P(glMultiDrawElementsEXT)
+P(glMultiTexCoordP1ui)
+P(glMultiTexCoordP1uiv)
+P(glMultiTexCoordP2ui)
+P(glMultiTexCoordP2uiv)
+P(glMultiTexCoordP3ui)
+P(glMultiTexCoordP3uiv)
+P(glMultiTexCoordP4ui)
+P(glMultiTexCoordP4uiv)
+P(glNormalP3ui)
+P(glNormalP3uiv)
+P(glNormalPointerEXT)
+P(glObjectPurgeableAPPLE)
+P(glObjectUnpurgeableAPPLE)
+P(glPassTexCoordATI)
+P(glPauseTransformFeedback)
+P(glPointParameterf)
+P(glPointParameterfARB)
+P(glPointParameterfEXT)
+P(glPointParameterfv)
+P(glPointParameterfvARB)
+P(glPointParameterfvEXT)
+P(glPointParameteri)
+P(glPointParameteriNV)
+P(glPointParameteriv)
+P(glPointParameterivNV)
+P(glPolygonOffsetEXT)
+P(glPrimitiveRestartIndex)
+P(glPrimitiveRestartIndexNV)
+P(glPrimitiveRestartNV)
+P(glPrioritizeTexturesEXT)
+P(glProgramEnvParameter4dARB)
+P(glProgramEnvParameter4dvARB)
+P(glProgramEnvParameter4fARB)
+P(glProgramEnvParameter4fvARB)
+P(glProgramLocalParameter4dARB)
+P(glProgramLocalParameter4dvARB)
+P(glProgramLocalParameter4fARB)
+P(glProgramLocalParameter4fvARB)
+P(glProgramNamedParameter4dNV)
+P(glProgramNamedParameter4dvNV)
+P(glProgramNamedParameter4fNV)
+P(glProgramNamedParameter4fvNV)
+P(glProgramParameter4dNV)
+P(glProgramParameter4dvNV)
+P(glProgramParameter4fNV)
+P(glProgramParameter4fvNV)
+P(glProgramParameteriARB)
+P(glProgramParameters4dvNV)
+P(glProgramParameters4fvNV)
+P(glProgramStringARB)
+P(glProvokingVertex)
+P(glProvokingVertexEXT)
+P(glReadBufferNV)
+P(glReadnPixelsARB)
+P(glReleaseShaderCompiler)
+P(glRenderbufferStorage)
+P(glRenderbufferStorageEXT)
+P(glRenderbufferStorageMultisample)
+P(glRenderbufferStorageMultisampleEXT)
+P(glRequestResidentProgramsNV)
+P(glResumeTransformFeedback)
+P(glSampleCoverageARB)
+P(glSampleMapATI)
+P(glSamplerParameterIiv)
+P(glSamplerParameterIuiv)
+P(glSamplerParameterf)
+P(glSamplerParameterfv)
+P(glSamplerParameteri)
+P(glSamplerParameteriv)
+P(glSecondaryColor3b)
+P(glSecondaryColor3bEXT)
+P(glSecondaryColor3bv)
+P(glSecondaryColor3bvEXT)
+P(glSecondaryColor3d)
+P(glSecondaryColor3dEXT)
+P(glSecondaryColor3dv)
+P(glSecondaryColor3dvEXT)
+P(glSecondaryColor3f)
+P(glSecondaryColor3fEXT)
+P(glSecondaryColor3fv)
+P(glSecondaryColor3fvEXT)
+P(glSecondaryColor3i)
+P(glSecondaryColor3iEXT)
+P(glSecondaryColor3iv)
+P(glSecondaryColor3ivEXT)
+P(glSecondaryColor3s)
+P(glSecondaryColor3sEXT)
+P(glSecondaryColor3sv)
+P(glSecondaryColor3svEXT)
+P(glSecondaryColor3ub)
+P(glSecondaryColor3ubEXT)
+P(glSecondaryColor3ubv)
+P(glSecondaryColor3ubvEXT)
+P(glSecondaryColor3ui)
+P(glSecondaryColor3uiEXT)
+P(glSecondaryColor3uiv)
+P(glSecondaryColor3uivEXT)
+P(glSecondaryColor3us)
+P(glSecondaryColor3usEXT)
+P(glSecondaryColor3usv)
+P(glSecondaryColor3usvEXT)
+P(glSecondaryColorP3ui)
+P(glSecondaryColorP3uiv)
+P(glSecondaryColorPointer)
+P(glSecondaryColorPointerEXT)
+P(glSetFragmentShaderConstantATI)
+P(glShaderBinary)
+P(glShaderSource)
+P(glShaderSourceARB)
+P(glStencilFuncSeparate)
+P(glStencilMaskSeparate)
+P(glStencilOpSeparate)
+P(glTexBuffer)
+P(glTexBufferARB)
+P(glTexBumpParameterfvATI)
+P(glTexBumpParameterivATI)
+P(glTexCoordP1ui)
+P(glTexCoordP1uiv)
+P(glTexCoordP2ui)
+P(glTexCoordP2uiv)
+P(glTexCoordP3ui)
+P(glTexCoordP3uiv)
+P(glTexCoordP4ui)
+P(glTexCoordP4uiv)
+P(glTexCoordPointerEXT)
+P(glTexImage3DEXT)
+P(glTexParameterIiv)
+P(glTexParameterIivEXT)
+P(glTexParameterIuiv)
+P(glTexParameterIuivEXT)
+P(glTexStorage1D)
+P(glTexStorage2D)
+P(glTexStorage3D)
+P(glTexSubImage1DEXT)
+P(glTexSubImage2DEXT)
+P(glTexSubImage3DEXT)
+P(glTextureBarrierNV)
+P(glTextureStorage1DEXT)
+P(glTextureStorage2DEXT)
+P(glTextureStorage3DEXT)
+P(glTrackMatrixNV)
+P(glTransformFeedbackVaryings)
+P(glTransformFeedbackVaryingsEXT)
+P(glUniform1f)
+P(glUniform1fARB)
+P(glUniform1fv)
+P(glUniform1fvARB)
+P(glUniform1i)
+P(glUniform1iARB)
+P(glUniform1iv)
+P(glUniform1ivARB)
+P(glUniform1ui)
+P(glUniform1uiEXT)
+P(glUniform1uiv)
+P(glUniform1uivEXT)
+P(glUniform2f)
+P(glUniform2fARB)
+P(glUniform2fv)
+P(glUniform2fvARB)
+P(glUniform2i)
+P(glUniform2iARB)
+P(glUniform2iv)
+P(glUniform2ivARB)
+P(glUniform2ui)
+P(glUniform2uiEXT)
+P(glUniform2uiv)
+P(glUniform2uivEXT)
+P(glUniform3f)
+P(glUniform3fARB)
+P(glUniform3fv)
+P(glUniform3fvARB)
+P(glUniform3i)
+P(glUniform3iARB)
+P(glUniform3iv)
+P(glUniform3ivARB)
+P(glUniform3ui)
+P(glUniform3uiEXT)
+P(glUniform3uiv)
+P(glUniform3uivEXT)
+P(glUniform4f)
+P(glUniform4fARB)
+P(glUniform4fv)
+P(glUniform4fvARB)
+P(glUniform4i)
+P(glUniform4iARB)
+P(glUniform4iv)
+P(glUniform4ivARB)
+P(glUniform4ui)
+P(glUniform4uiEXT)
+P(glUniform4uiv)
+P(glUniform4uivEXT)
+P(glUniformBlockBinding)
+P(glUniformMatrix2fv)
+P(glUniformMatrix2fvARB)
+P(glUniformMatrix2x3fv)
+P(glUniformMatrix2x4fv)
+P(glUniformMatrix3fv)
+P(glUniformMatrix3fvARB)
+P(glUniformMatrix3x2fv)
+P(glUniformMatrix3x4fv)
+P(glUniformMatrix4fv)
+P(glUniformMatrix4fvARB)
+P(glUniformMatrix4x2fv)
+P(glUniformMatrix4x3fv)
+P(glUnlockArraysEXT)
+P(glUnmapBuffer)
+P(glUnmapBufferARB)
+P(glUseProgram)
+P(glUseProgramObjectARB)
+P(glUseShaderProgramEXT)
+P(glValidateProgram)
+P(glValidateProgramARB)
+P(glVertexAttrib1d)
+P(glVertexAttrib1dARB)
+P(glVertexAttrib1dNV)
+P(glVertexAttrib1dv)
+P(glVertexAttrib1dvARB)
+P(glVertexAttrib1dvNV)
+P(glVertexAttrib1f)
+P(glVertexAttrib1fARB)
+P(glVertexAttrib1fNV)
+P(glVertexAttrib1fv)
+P(glVertexAttrib1fvARB)
+P(glVertexAttrib1fvNV)
+P(glVertexAttrib1s)
+P(glVertexAttrib1sARB)
+P(glVertexAttrib1sNV)
+P(glVertexAttrib1sv)
+P(glVertexAttrib1svARB)
+P(glVertexAttrib1svNV)
+P(glVertexAttrib2d)
+P(glVertexAttrib2dARB)
+P(glVertexAttrib2dNV)
+P(glVertexAttrib2dv)
+P(glVertexAttrib2dvARB)
+P(glVertexAttrib2dvNV)
+P(glVertexAttrib2f)
+P(glVertexAttrib2fARB)
+P(glVertexAttrib2fNV)
+P(glVertexAttrib2fv)
+P(glVertexAttrib2fvARB)
+P(glVertexAttrib2fvNV)
+P(glVertexAttrib2s)
+P(glVertexAttrib2sARB)
+P(glVertexAttrib2sNV)
+P(glVertexAttrib2sv)
+P(glVertexAttrib2svARB)
+P(glVertexAttrib2svNV)
+P(glVertexAttrib3d)
+P(glVertexAttrib3dARB)
+P(glVertexAttrib3dNV)
+P(glVertexAttrib3dv)
+P(glVertexAttrib3dvARB)
+P(glVertexAttrib3dvNV)
+P(glVertexAttrib3f)
+P(glVertexAttrib3fARB)
+P(glVertexAttrib3fNV)
+P(glVertexAttrib3fv)
+P(glVertexAttrib3fvARB)
+P(glVertexAttrib3fvNV)
+P(glVertexAttrib3s)
+P(glVertexAttrib3sARB)
+P(glVertexAttrib3sNV)
+P(glVertexAttrib3sv)
+P(glVertexAttrib3svARB)
+P(glVertexAttrib3svNV)
+P(glVertexAttrib4Nbv)
+P(glVertexAttrib4NbvARB)
+P(glVertexAttrib4Niv)
+P(glVertexAttrib4NivARB)
+P(glVertexAttrib4Nsv)
+P(glVertexAttrib4NsvARB)
+P(glVertexAttrib4Nub)
+P(glVertexAttrib4NubARB)
+P(glVertexAttrib4Nubv)
+P(glVertexAttrib4NubvARB)
+P(glVertexAttrib4Nuiv)
+P(glVertexAttrib4NuivARB)
+P(glVertexAttrib4Nusv)
+P(glVertexAttrib4NusvARB)
+P(glVertexAttrib4bv)
+P(glVertexAttrib4bvARB)
+P(glVertexAttrib4d)
+P(glVertexAttrib4dARB)
+P(glVertexAttrib4dNV)
+P(glVertexAttrib4dv)
+P(glVertexAttrib4dvARB)
+P(glVertexAttrib4dvNV)
+P(glVertexAttrib4f)
+P(glVertexAttrib4fARB)
+P(glVertexAttrib4fNV)
+P(glVertexAttrib4fv)
+P(glVertexAttrib4fvARB)
+P(glVertexAttrib4fvNV)
+P(glVertexAttrib4iv)
+P(glVertexAttrib4ivARB)
+P(glVertexAttrib4s)
+P(glVertexAttrib4sARB)
+P(glVertexAttrib4sNV)
+P(glVertexAttrib4sv)
+P(glVertexAttrib4svARB)
+P(glVertexAttrib4svNV)
+P(glVertexAttrib4ubNV)
+P(glVertexAttrib4ubv)
+P(glVertexAttrib4ubvARB)
+P(glVertexAttrib4ubvNV)
+P(glVertexAttrib4uiv)
+P(glVertexAttrib4uivARB)
+P(glVertexAttrib4usv)
+P(glVertexAttrib4usvARB)
+P(glVertexAttribDivisor)
+P(glVertexAttribDivisorARB)
+P(glVertexAttribI1i)
+P(glVertexAttribI1iEXT)
+P(glVertexAttribI1iv)
+P(glVertexAttribI1ivEXT)
+P(glVertexAttribI1ui)
+P(glVertexAttribI1uiEXT)
+P(glVertexAttribI1uiv)
+P(glVertexAttribI1uivEXT)
+P(glVertexAttribI2i)
+P(glVertexAttribI2iEXT)
+P(glVertexAttribI2iv)
+P(glVertexAttribI2ivEXT)
+P(glVertexAttribI2ui)
+P(glVertexAttribI2uiEXT)
+P(glVertexAttribI2uiv)
+P(glVertexAttribI2uivEXT)
+P(glVertexAttribI3i)
+P(glVertexAttribI3iEXT)
+P(glVertexAttribI3iv)
+P(glVertexAttribI3ivEXT)
+P(glVertexAttribI3ui)
+P(glVertexAttribI3uiEXT)
+P(glVertexAttribI3uiv)
+P(glVertexAttribI3uivEXT)
+P(glVertexAttribI4bv)
+P(glVertexAttribI4bvEXT)
+P(glVertexAttribI4i)
+P(glVertexAttribI4iEXT)
+P(glVertexAttribI4iv)
+P(glVertexAttribI4ivEXT)
+P(glVertexAttribI4sv)
+P(glVertexAttribI4svEXT)
+P(glVertexAttribI4ubv)
+P(glVertexAttribI4ubvEXT)
+P(glVertexAttribI4ui)
+P(glVertexAttribI4uiEXT)
+P(glVertexAttribI4uiv)
+P(glVertexAttribI4uivEXT)
+P(glVertexAttribI4usv)
+P(glVertexAttribI4usvEXT)
+P(glVertexAttribIPointer)
+P(glVertexAttribIPointerEXT)
+P(glVertexAttribP1ui)
+P(glVertexAttribP1uiv)
+P(glVertexAttribP2ui)
+P(glVertexAttribP2uiv)
+P(glVertexAttribP3ui)
+P(glVertexAttribP3uiv)
+P(glVertexAttribP4ui)
+P(glVertexAttribP4uiv)
+P(glVertexAttribPointer)
+P(glVertexAttribPointerARB)
+P(glVertexAttribPointerNV)
+P(glVertexAttribs1dvNV)
+P(glVertexAttribs1fvNV)
+P(glVertexAttribs1svNV)
+P(glVertexAttribs2dvNV)
+P(glVertexAttribs2fvNV)
+P(glVertexAttribs2svNV)
+P(glVertexAttribs3dvNV)
+P(glVertexAttribs3fvNV)
+P(glVertexAttribs3svNV)
+P(glVertexAttribs4dvNV)
+P(glVertexAttribs4fvNV)
+P(glVertexAttribs4svNV)
+P(glVertexAttribs4ubvNV)
+P(glVertexP2ui)
+P(glVertexP2uiv)
+P(glVertexP3ui)
+P(glVertexP3uiv)
+P(glVertexP4ui)
+P(glVertexP4uiv)
+P(glVertexPointerEXT)
+P(glWaitSync)
+P(glWindowPos2d)
+P(glWindowPos2dARB)
+P(glWindowPos2dv)
+P(glWindowPos2dvARB)
+P(glWindowPos2f)
+P(glWindowPos2fARB)
+P(glWindowPos2fv)
+P(glWindowPos2fvARB)
+P(glWindowPos2i)
+P(glWindowPos2iARB)
+P(glWindowPos2iv)
+P(glWindowPos2ivARB)
+P(glWindowPos2s)
+P(glWindowPos2sARB)
+P(glWindowPos2sv)
+P(glWindowPos2svARB)
+P(glWindowPos3d)
+P(glWindowPos3dARB)
+P(glWindowPos3dv)
+P(glWindowPos3dvARB)
+P(glWindowPos3f)
+P(glWindowPos3fARB)
+P(glWindowPos3fv)
+P(glWindowPos3fvARB)
+P(glWindowPos3i)
+P(glWindowPos3iARB)
+P(glWindowPos3iv)
+P(glWindowPos3ivARB)
+P(glWindowPos3s)
+P(glWindowPos3sARB)
+P(glWindowPos3sv)
+P(glWindowPos3svARB)
diff --git a/glx-dpyredir.def b/glx-dpyredir.def
new file mode 100644 (file)
index 0000000..295ee7b
--- /dev/null
@@ -0,0 +1,11 @@
+// GLX functions which need to be simply forwarded
+DEF_GLX_PROTO(void,         glXCopyContext,           (Display *dpy, GLXContext src, GLXContext dst, unsigned long mask),src,dst,mask)
+DEF_GLX_PROTO(Bool,         glXQueryExtension,        (Display *dpy, int *errorb, int *event),errorb,event)
+DEF_GLX_PROTO(Bool,         glXQueryVersion,          (Display *dpy, int *maj, int *min),maj,min)
+DEF_GLX_PROTO(Bool,         glXIsDirect,              (Display *dpy, GLXContext ctx),ctx)
+DEF_GLX_PROTO(const char*,  glXQueryServerString,     (Display *dpy, int screen, int name),screen,name)
+DEF_GLX_PROTO(GLXFBConfig*, glXChooseFBConfig,        (Display *dpy, int screen, const int *attribList, int *nitems),screen,attribList,nitems)
+DEF_GLX_PROTO(GLXFBConfig*, glXGetFBConfigs,          (Display *dpy, int screen, int *nelements),screen,nelements)
+DEF_GLX_PROTO(int,          glXQueryContext,          (Display *dpy, GLXContext ctx, int attribute, int *value),ctx,attribute,value)
+DEF_GLX_PROTO(void,         glXSelectEvent,           (Display *dpy, GLXDrawable drawable, unsigned long mask),drawable,mask)
+DEF_GLX_PROTO(void,         glXGetSelectedEvent,      (Display *dpy, GLXDrawable drawable, unsigned long *mask),drawable,mask)
diff --git a/glx-reimpl.def b/glx-reimpl.def
new file mode 100644 (file)
index 0000000..4996443
--- /dev/null
@@ -0,0 +1,36 @@
+// GLX Functions implemented by primus
+DEF_GLX_PROTO(GLXContext, glXCreateContext,     (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct))
+DEF_GLX_PROTO(GLXContext, glXCreateNewContext,  (Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct))
+DEF_GLX_PROTO(void,       glXDestroyContext,    (Display *dpy, GLXContext ctx))
+DEF_GLX_PROTO(Bool,       glXMakeCurrent,       (Display *dpy, GLXDrawable drawable, GLXContext ctx))
+DEF_GLX_PROTO(Bool,       glXMakeContextCurrent,(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx))
+DEF_GLX_PROTO(void,       glXSwapBuffers,       (Display *dpy, GLXDrawable drawable))
+
+DEF_GLX_PROTO(__GLXextFuncPtr, glXGetProcAddressARB, (const GLubyte *))
+DEF_GLX_PROTO(__GLXextFuncPtr, glXGetProcAddress,    (const GLubyte *))
+
+DEF_GLX_PROTO(const char*,  glXGetClientString,       (Display *dpy, int name),name)
+DEF_GLX_PROTO(const char*,  glXQueryExtensionsString, (Display *dpy, int screen),screen)
+
+DEF_GLX_PROTO(GLXWindow,    glXCreateWindow,          (Display *dpy, GLXFBConfig config, Window win, const int *attribList),config,win,attribList)
+DEF_GLX_PROTO(void,         glXDestroyWindow,         (Display *dpy, GLXWindow window),window)
+DEF_GLX_PROTO(GLXPbuffer,   glXCreatePbuffer,         (Display *dpy, GLXFBConfig config, const int *attribList),config,attribList)
+DEF_GLX_PROTO(void,         glXDestroyPbuffer,        (Display *dpy, GLXPbuffer pbuf),pbuf)
+DEF_GLX_PROTO(GLXPixmap,    glXCreatePixmap,          (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList),config,pixmap,attribList)
+DEF_GLX_PROTO(void,         glXDestroyPixmap,         (Display *dpy, GLXPixmap pixmap),pixmap)
+DEF_GLX_PROTO(GLXPixmap,    glXCreateGLXPixmap,       (Display *dpy, XVisualInfo *visual, Pixmap pixmap),visual,pixmap)
+DEF_GLX_PROTO(void,         glXDestroyGLXPixmap,      (Display *dpy, GLXPixmap pixmap),pixmap)
+DEF_GLX_PROTO(XVisualInfo*, glXGetVisualFromFBConfig, (Display *dpy, GLXFBConfig config),config)
+DEF_GLX_PROTO(int,          glXGetFBConfigAttrib,     (Display *dpy, GLXFBConfig config, int attribute, int *value),config,attribute,value)
+DEF_GLX_PROTO(void,         glXQueryDrawable,         (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value),draw,attribute,value)
+
+DEF_GLX_PROTO(XVisualInfo*, glXChooseVisual,          (Display *dpy, int screen, int *attribList),screen,attribList)
+DEF_GLX_PROTO(int,          glXGetConfig,             (Display *dpy, XVisualInfo *visual, int attrib, int *value),visual,attrib,value)
+
+DEF_GLX_PROTO(void,         glXUseXFont,              (Font font, int first, int count, int list))
+DEF_GLX_PROTO(GLXContext,   glXGetCurrentContext,     (void))
+DEF_GLX_PROTO(GLXDrawable,  glXGetCurrentDrawable,    (void))
+DEF_GLX_PROTO(void,         glXWaitGL,                (void))
+DEF_GLX_PROTO(void,         glXWaitX,                 (void))
+DEF_GLX_PROTO(Display*,     glXGetCurrentDisplay,     (void))
+DEF_GLX_PROTO(GLXDrawable,  glXGetCurrentReadDrawable,(void))
diff --git a/glxext-reimpl.def b/glxext-reimpl.def
new file mode 100644 (file)
index 0000000..888f7ce
--- /dev/null
@@ -0,0 +1,3 @@
+// GLX extension functions implemented in primus
+DEF_GLX_PROTO(int,          glXSwapIntervalSGI,       (int interval))
+DEF_GLX_PROTO(GLXContext,   glXCreateContextAttribsARB,(Display *dpy, GLXFBConfig config, GLXContext shareList, Bool direct, const int *attrib_list))
diff --git a/libglfork.cpp b/libglfork.cpp
new file mode 100644 (file)
index 0000000..03f514f
--- /dev/null
@@ -0,0 +1,1033 @@
+#include <dlfcn.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+#include <cassert>
+#include <map>
+#include <string>
+#include <X11/Xatom.h>
+#pragma GCC visibility push(default)
+#define GLX_GLXEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+#include <GL/glx.h>
+#pragma GCC visibility pop
+
+#define primus_print(c, ...) do { if (c) fprintf(stderr, "primus: " __VA_ARGS__); } while (0)
+
+#define die_if(cond, ...)  do {if (cond) {primus_print(true, "fatal: " __VA_ARGS__); exit(1);} } while (0)
+#define primus_warn(...) primus_print(primus.loglevel >= 1, "warning: " __VA_ARGS__)
+#define primus_perf(...) primus_print(primus.loglevel >= 2, "profiling: " __VA_ARGS__)
+
+// Try to load any of the colon-separated libraries
+static void *mdlopen(const char *paths, int flag)
+{
+  char *p = strdupa(paths);
+  char errors[1024], *errors_ptr = errors, *errors_end = errors + 1024;
+  for (char *c = p; c; p = c + 1)
+  {
+    if ((c = strchr(p, ':')))
+      *c = 0;
+    die_if(p[0] != '/', "need absolute library path: %s\n", p);
+    void *handle = dlopen(p, flag);
+    if (handle)
+      return handle;
+    errors_ptr += snprintf(errors_ptr, errors_end - errors_ptr, "%s\n", dlerror());
+  }
+  die_if(true, "failed to load any of the libraries: %s\n%s", paths, errors);
+}
+
+static void *real_dlsym(void *handle, const char *symbol)
+{
+  typedef void* (*dlsym_fn)(void *, const char*);
+  static dlsym_fn pdlsym = (dlsym_fn) dlsym(dlopen("libdl.so.2", RTLD_LAZY), "dlsym");
+  return pdlsym(handle, symbol);
+}
+
+// Pointers to implemented/forwarded GLX and OpenGL functions
+struct CapturedFns {
+  void *handle;
+  // Declare functions as fields of the struct
+#define DEF_GLX_PROTO(ret, name, args, ...) ret (*name) args;
+#include "glx-reimpl.def"
+#include "glx-dpyredir.def"
+#include "glxext-reimpl.def"
+#include "gl-passthru.def"
+#include "gl-needed.def"
+#undef DEF_GLX_PROTO
+  CapturedFns(const char *lib)
+  {
+    handle = mdlopen(lib, RTLD_LAZY);
+#define DEF_GLX_PROTO(ret, name, args, ...) name = (ret (*) args)real_dlsym(handle, #name);
+#include "glx-reimpl.def"
+#include "glx-dpyredir.def"
+#undef DEF_GLX_PROTO
+#define DEF_GLX_PROTO(ret, name, args, ...) name = (ret (*) args)this->glXGetProcAddress((GLubyte*)#name);
+#include "glxext-reimpl.def"
+#include "gl-passthru.def"
+#include "gl-needed.def"
+#undef DEF_GLX_PROTO
+  }
+  ~CapturedFns()
+  {
+    dlclose(handle);
+  }
+};
+
+// Drawable tracking info
+struct DrawableInfo {
+  // Only XWindow is not explicitely created via GLX
+  enum {XWindow, Window, Pixmap, Pbuffer} kind;
+  GLXFBConfig fbconfig;
+  GLXPbuffer  pbuffer;
+  Drawable window;
+  int width, height;
+  enum ReinitTodo {NONE, RESIZE, SHUTDOWN} reinit;
+  GLvoid *pixeldata;
+  GLsync sync;
+  GLXContext actx;
+
+  struct {
+    pthread_t worker;
+    sem_t acqsem, relsem;
+    ReinitTodo reinit;
+
+    void spawn_worker(GLXDrawable draw, void* (*work)(void*))
+    {
+      reinit = RESIZE;
+      sem_init(&acqsem, 0, 0);
+      sem_init(&relsem, 0, 0);
+      pthread_create(&worker, NULL, work, (void*)draw);
+    }
+    void reap_worker()
+    {
+      //pthread_cancel(worker);
+      pthread_join(worker, NULL);
+      sem_destroy(&relsem);
+      sem_destroy(&acqsem);
+      worker = 0;
+    }
+  } r, d;
+  void reap_workers()
+  {
+    if (r.worker)
+    {
+      r.reinit = SHUTDOWN;
+      sem_post(&r.acqsem);
+      sem_wait(&r.relsem);
+      r.reap_worker();
+      d.reap_worker();
+    }
+  }
+  void update_geometry(int width, int height)
+  {
+    if (this->width == width && this->height == height)
+      return;
+    this->width = width; this->height = height;
+    __sync_synchronize();
+    reinit = RESIZE;
+  }
+  ~DrawableInfo();
+};
+
+struct DrawablesInfo: public std::map<GLXDrawable, DrawableInfo> {
+  bool known(GLXDrawable draw)
+  {
+    return this->find(draw) != this->end();
+  }
+};
+
+struct ContextInfo {
+  GLXFBConfig fbconfig;
+  int sharegroup;
+};
+
+struct ContextsInfo: public std::map<GLXContext, ContextInfo> {
+  void record(GLXContext ctx, GLXFBConfig config, GLXContext share)
+  {
+    static int nsharegroups;
+    int sharegroup = share ? (*this)[share].sharegroup : nsharegroups++;
+    (*this)[ctx] = (ContextInfo){config, sharegroup};
+  }
+};
+
+// Shorthand for obtaining compile-time configurable value that can be
+// overridden by environment
+#define getconf(V) (getenv(#V) ? getenv(#V) : V)
+
+// Runs before all other initialization takes place
+struct EarlyInitializer {
+  EarlyInitializer(const char **adpy_strp, const char **libgla_strp)
+  {
+#ifdef BUMBLEBEE_SOCKET
+    // Signal the Bumblebee daemon to bring up secondary X
+    int sock = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+    struct sockaddr_un addr;
+    addr.sun_family = AF_UNIX;
+    strncpy(addr.sun_path, getconf(BUMBLEBEE_SOCKET), sizeof(addr.sun_path));
+    die_if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0,
+           "failed to connect to Bumblebee daemon: %s\n", strerror(errno));
+    static char c[256];
+    if (!getenv("PRIMUS_DISPLAY"))
+    {
+      send(sock, "Q VirtualDisplay", strlen("Q VirtualDisplay") + 1, 0);
+      recv(sock, &c, 255, 0);
+      die_if(memcmp(c, "Value: ", strlen("Value: ")), "unexpected query response\n");
+      *strchrnul(c, '\n') = 0;
+      *adpy_strp = strdup(c + 7);
+    }
+    if (!getenv("PRIMUS_libGLa"))
+    {
+      send(sock, "Q LibraryPath", strlen("Q LibraryPath") + 1, 0);
+      recv(sock, &c, 255, 0);
+      die_if(memcmp(c, "Value: ", strlen("Value: ")), "unexpected query response\n");
+      *strchrnul(c, '\n') = 0;
+      int npaths = 0;
+      for (char *p = c + 7; *p; npaths++, p = strchrnul(p + 1, ':'));
+      if (npaths)
+      {
+       char *bblibs = new char[strlen(c + 7) + npaths * strlen("/libGL.so.1") + 1], *b = bblibs, *n, *p;
+       for (p = c + 7; *p; p = n)
+       {
+         n = strchrnul(p + 1, ':');
+         b += sprintf(b, "%.*s/libGL.so.1", (int)(n - p), p);
+       }
+       *libgla_strp = bblibs;
+      }
+    }
+    send(sock, "C", 1, 0);
+    recv(sock, &c, 255, 0);
+    die_if(c[0] == 'N', "Bumblebee daemon reported: %s\n", c + 5);
+    die_if(c[0] != 'Y', "failure contacting Bumblebee daemon\n");
+    // the socket will be closed when the application quits, then bumblebee will shut down the secondary X
+#else
+#warning Building without Bumblebee daemon support
+#endif
+  }
+};
+
+// Process-wide data
+static struct PrimusInfo {
+  const char *adpy_str, *libgla_str;
+  EarlyInitializer ei;
+  // Readback-display synchronization method
+  // 0: no sync, 1: D lags behind one frame, 2: fully synced
+  int sync;
+  // 0: only errors, 1: warnings, 2: profiling
+  int loglevel;
+  // 0: autodetect, 1: texture, 2: PBO glDrawPixels
+  int dispmethod;
+  // sleep ratio in readback thread, percent
+  int autosleep;
+  // The "accelerating" X display
+  Display *adpy;
+  // The "displaying" X display. The same as the application is using, but
+  // primus opens its own connection.
+  Display *ddpy;
+  // An artifact: primus needs to make symbols from libglapi.so globally
+  // visible before loading Mesa
+  const void *needed_global;
+  CapturedFns afns;
+  CapturedFns dfns;
+  // FIXME: there are race conditions in accesses to these
+  DrawablesInfo drawables;
+  ContextsInfo contexts;
+
+  PrimusInfo():
+    adpy_str(getconf(PRIMUS_DISPLAY)),
+    libgla_str(getconf(PRIMUS_libGLa)),
+    ei(&adpy_str, &libgla_str),
+    sync(atoi(getconf(PRIMUS_SYNC))),
+    loglevel(atoi(getconf(PRIMUS_VERBOSE))),
+    dispmethod(atoi(getconf(PRIMUS_UPLOAD))),
+    autosleep(atoi(getconf(PRIMUS_SLEEP))),
+    adpy(XOpenDisplay(adpy_str)),
+    ddpy(XOpenDisplay(NULL)),
+    needed_global(dlopen(getconf(PRIMUS_LOAD_GLOBAL), RTLD_LAZY | RTLD_GLOBAL)),
+    afns(libgla_str),
+    dfns(getconf(PRIMUS_libGLd))
+  {
+    die_if(!adpy, "failed to open secondary X display\n");
+    die_if(!ddpy, "failed to open main X display\n");
+    die_if(!needed_global, "failed to load PRIMUS_LOAD_GLOBAL\n");
+  }
+} primus;
+
+// Thread-specific data
+static __thread struct {
+  Display *dpy;
+  GLXDrawable drawable, read_drawable;
+  void make_current(Display *dpy, GLXDrawable draw, GLXDrawable read)
+  {
+    this->dpy = dpy;
+    this->drawable = draw;
+    this->read_drawable = read;
+  }
+} tsdata;
+
+// Profiler
+struct Profiler {
+  const char *name;
+  const char * const *state_names;
+
+  double state_time[6], prev_timestamp, print_timestamp;
+  int state, nframes, width, height;
+
+  static double get_timestamp()
+  {
+    struct timespec tp;
+    clock_gettime(CLOCK_MONOTONIC, &tp);
+    return tp.tv_sec + 1e-9 * tp.tv_nsec;
+  }
+
+  Profiler(const char *name, const char * const *state_names):
+    name(name),
+    state_names(state_names),
+    state(0), nframes(0), width(0), height(0)
+  {
+    memset(state_time, 0, sizeof(state_time));
+    prev_timestamp = print_timestamp = get_timestamp();
+  }
+
+  void tick(bool state_reset = false)
+  {
+    if (primus.loglevel < 2)
+      return;
+    double timestamp = get_timestamp();
+    assert(state_reset || state_names[state]);
+    if (state_reset)
+      state = 0;
+    assert(state * sizeof(state_time[0]) < sizeof(state_time));
+    state_time[state++] += timestamp - prev_timestamp;
+    prev_timestamp = timestamp;
+    if (state_names[state])
+      return;
+    nframes++;
+    // check if it's time to print again
+    double period = timestamp - print_timestamp; // time since we printed
+    if (period < 5)
+      return;
+    // construct output
+    char buf[128], *cbuf = buf, *end = buf+128;
+    for (int i = 0; i < state; i++)
+      cbuf += snprintf(cbuf, end - cbuf, ", %.1f%% %s", 100 * state_time[i] / period, state_names[i]);
+    primus_perf("%s: %dx%d, %.1f fps%s\n", name, width, height, nframes / period, buf);
+    // start counting again
+    print_timestamp = timestamp;
+    nframes = 0;
+    memset(state_time, 0, sizeof(state_time));
+  }
+};
+
+// Find out the dimensions of the window
+static void note_geometry(Display *dpy, Drawable draw, int *width, int *height)
+{
+  Window root;
+  int x, y;
+  unsigned bw, d;
+  XGetGeometry(dpy, draw, &root, &x, &y, (unsigned *)width, (unsigned *)height, &bw, &d);
+}
+
+static GLXFBConfig* get_dconfigs(Display *dpy)
+{
+  static const int attrs[] = {GLX_DOUBLEBUFFER, GL_TRUE, None};
+  int ncfg;
+  GLXFBConfig *dconfigs = primus.dfns.glXChooseFBConfig(dpy, 0, attrs, &ncfg);
+  die_if(!dconfigs, "broken GLX on main X display\n");
+  return dconfigs;
+}
+
+static bool test_drawpixels_fast(Display *dpy, GLXContext ctx, GLXFBConfig dconfig)
+{
+  int width = 1920, height = 1080;
+  int pbattrs[] = {GLX_PBUFFER_WIDTH, width, GLX_PBUFFER_HEIGHT, height, GLX_PRESERVED_CONTENTS, True, None};
+  GLXPbuffer pbuffer = primus.dfns.glXCreatePbuffer(dpy, dconfig, pbattrs);
+  primus.dfns.glXMakeCurrent(dpy, pbuffer, ctx);
+  GLuint pbo;
+  primus.dfns.glGenBuffers(1, &pbo);
+  primus.dfns.glBindBuffer(GL_PIXEL_UNPACK_BUFFER_EXT, pbo);
+  primus.dfns.glBufferData(GL_PIXEL_UNPACK_BUFFER_EXT, width*height*4, NULL, GL_STREAM_DRAW);
+  void *pixeldata = malloc(width*height*4);
+
+  double end = 0.2 + Profiler::get_timestamp();
+  int iters = 0;
+  do {
+    primus.dfns.glBufferSubData(GL_PIXEL_UNPACK_BUFFER_EXT, 0, width*height*4, pixeldata);
+    primus.dfns.glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+    primus.dfns.glXSwapBuffers(dpy, pbuffer);
+    iters++;
+  } while (end > Profiler::get_timestamp());
+
+  free(pixeldata);
+  primus.dfns.glDeleteBuffers(1, &pbo);
+  primus.dfns.glXDestroyPbuffer(dpy, pbuffer);
+
+  bool is_fast = iters >= 12;
+  primus_perf("upload autodetection: will use %s path (%d iters)\n", is_fast ? "PBO" : "texture", iters);
+  return is_fast;
+}
+
+static void* display_work(void *vd)
+{
+  GLXDrawable drawable = (GLXDrawable)vd;
+  DrawableInfo &di = primus.drawables[drawable];
+  int width, height;
+  static const float quad_vertex_coords[]  = {-1, -1, -1, 1, 1, 1, 1, -1};
+  static const float quad_texture_coords[] = { 0,  0,  0, 1, 1, 1, 1,  0};
+  GLuint textures[2] = {0}, pbos[2] = {0};
+  int ctex = 0;
+  static const char *state_names[] = {"wait", "upload", "draw+swap", NULL};
+  Profiler profiler("display", state_names);
+  Display *ddpy = XOpenDisplay(NULL);
+  if (!ddpy) // Chromium sandbox prevents opening new connections
+  {
+    ddpy = primus.ddpy;
+    primus_warn("reusing initial X connection for display thread\n");
+  }
+  assert(di.kind == di.XWindow || di.kind == di.Window);
+  XSelectInput(ddpy, di.window, StructureNotifyMask);
+  note_geometry(ddpy, di.window, &width, &height);
+  di.update_geometry(width, height);
+  GLXFBConfig *dconfigs = get_dconfigs(ddpy);
+  GLXContext context = primus.dfns.glXCreateNewContext(ddpy, *dconfigs, GLX_RGBA_TYPE, NULL, True);
+  die_if(!primus.dfns.glXIsDirect(ddpy, context),
+        "failed to acquire direct rendering context for display thread\n");
+  if (!primus.dispmethod)
+    primus.dispmethod = test_drawpixels_fast(ddpy, context, *dconfigs) ? 2 : 1;
+  XFree(dconfigs);
+  primus.dfns.glXMakeCurrent(ddpy, di.window, context);
+  bool use_textures = (primus.dispmethod == 1);
+  if (use_textures)
+  {
+    primus.dfns.glVertexPointer  (2, GL_FLOAT, 0, quad_vertex_coords);
+    primus.dfns.glTexCoordPointer(2, GL_FLOAT, 0, quad_texture_coords);
+    primus.dfns.glEnableClientState(GL_VERTEX_ARRAY);
+    primus.dfns.glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+    primus.dfns.glGenTextures(2, textures);
+    primus.dfns.glEnable(GL_TEXTURE_2D);
+  }
+  else
+    primus.dfns.glGenBuffers(2, pbos);
+  for (;;)
+  {
+    sem_wait(&di.d.acqsem);
+    profiler.tick(true);
+    if (di.d.reinit)
+    {
+      if (di.d.reinit == di.SHUTDOWN)
+      {
+       if (use_textures)
+         primus.dfns.glDeleteTextures(2, textures);
+       else
+         primus.dfns.glDeleteBuffers(2, pbos);
+       primus.dfns.glXMakeCurrent(ddpy, 0, NULL);
+       primus.dfns.glXDestroyContext(ddpy, context);
+       if (ddpy != primus.ddpy)
+         XCloseDisplay(ddpy);
+       sem_post(&di.d.relsem);
+       return NULL;
+      }
+      di.d.reinit = di.NONE;
+      profiler.width = width = di.width;
+      profiler.height = height = di.height;
+      primus.dfns.glViewport(0, 0, width, height);
+      if (use_textures)
+      {
+       primus.dfns.glBindTexture(GL_TEXTURE_2D, textures[ctex ^ 1]);
+       primus.dfns.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       primus.dfns.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+       primus.dfns.glBindTexture(GL_TEXTURE_2D, textures[ctex]);
+       primus.dfns.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       primus.dfns.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+      }
+      else
+      {
+       primus.dfns.glBindBuffer(GL_PIXEL_UNPACK_BUFFER_EXT, pbos[ctex ^ 1]);
+       primus.dfns.glBufferData(GL_PIXEL_UNPACK_BUFFER_EXT, width*height*4, NULL, GL_STREAM_DRAW);
+       primus.dfns.glBindBuffer(GL_PIXEL_UNPACK_BUFFER_EXT, pbos[ctex]);
+       primus.dfns.glBufferData(GL_PIXEL_UNPACK_BUFFER_EXT, width*height*4, NULL, GL_STREAM_DRAW);
+      }
+      sem_post(&di.d.relsem);
+      continue;
+    }
+    if (use_textures)
+      primus.dfns.glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, di.pixeldata);
+    else
+      primus.dfns.glBufferSubData(GL_PIXEL_UNPACK_BUFFER_EXT, 0, width*height*4, di.pixeldata);
+    if (!primus.sync)
+      sem_post(&di.d.relsem); // Unlock as soon as possible
+    profiler.tick();
+    if (use_textures)
+    {
+      primus.dfns.glDrawArrays(GL_QUADS, 0, 4);
+      primus.dfns.glBindTexture(GL_TEXTURE_2D, textures[ctex ^= 1]);
+    }
+    else
+    {
+      primus.dfns.glDrawPixels(width, height, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+      primus.dfns.glBindBuffer(GL_PIXEL_UNPACK_BUFFER_EXT, pbos[ctex ^= 1]);
+    }
+    primus.dfns.glXSwapBuffers(ddpy, di.window);
+    for (int pending = XPending(ddpy); pending > 0; pending--)
+    {
+      XEvent event;
+      XNextEvent(ddpy, &event);
+      if (event.type == ConfigureNotify)
+       di.update_geometry(event.xconfigure.width, event.xconfigure.height);
+    }
+    if (primus.sync)
+      sem_post(&di.d.relsem); // Unlock only after drawing
+    profiler.tick();
+  }
+  return NULL;
+}
+
+static void* readback_work(void *vd)
+{
+  GLXDrawable drawable = (GLXDrawable)vd;
+  DrawableInfo &di = primus.drawables[drawable];
+  int width, height;
+  GLuint pbos[2] = {0};
+  int cbuf = 0;
+  unsigned sleep_usec = 0;
+  static const char *state_names[] = {"app", "sleep", "map", "wait", NULL};
+  Profiler profiler("readback", state_names);
+  struct timespec tp;
+  if (!primus.sync)
+    sem_post(&di.d.relsem); // No PBO is mapped initially
+  GLXContext context = primus.afns.glXCreateNewContext(primus.adpy, di.fbconfig, GLX_RGBA_TYPE, di.actx, True);
+  die_if(!primus.afns.glXIsDirect(primus.adpy, context),
+        "failed to acquire direct rendering context for readback thread\n");
+  primus.afns.glXMakeCurrent(primus.adpy, di.pbuffer, context);
+  primus.afns.glGenBuffers(2, &pbos[0]);
+  primus.afns.glReadBuffer(GL_FRONT);
+  for (;;)
+  {
+    sem_wait(&di.r.acqsem);
+    profiler.tick(true);
+    if (di.r.reinit)
+    {
+      clock_gettime(CLOCK_REALTIME, &tp);
+      tp.tv_sec  += 1;
+      // Wait for D worker, if active
+      if (!primus.sync && sem_timedwait(&di.d.relsem, &tp))
+      {
+       pthread_cancel(di.d.worker);
+       sem_post(&di.d.relsem); // Pretend that D worker completed reinit
+       primus_warn("timeout waiting for display worker\n");
+       die_if(di.r.reinit != di.SHUTDOWN, "killed worker on resize\n");
+      }
+      di.d.reinit = di.r.reinit;
+      sem_post(&di.d.acqsem); // Signal D worker to reinit
+      sem_wait(&di.d.relsem); // Wait until reinit was completed
+      if (!primus.sync)
+       sem_post(&di.d.relsem); // Unlock as no PBO is currently mapped
+      if (di.r.reinit == di.SHUTDOWN)
+      {
+       primus.afns.glBindBuffer(GL_PIXEL_PACK_BUFFER_EXT, pbos[cbuf ^ 1]);
+       primus.afns.glUnmapBuffer(GL_PIXEL_PACK_BUFFER_EXT);
+       primus.afns.glDeleteBuffers(2, &pbos[0]);
+       primus.afns.glXMakeCurrent(primus.adpy, 0, NULL);
+       primus.afns.glXDestroyContext(primus.adpy, context);
+       sem_post(&di.r.relsem);
+       return NULL;
+      }
+      di.r.reinit = di.NONE;
+      profiler.width = width = di.width;
+      profiler.height = height = di.height;
+      primus.afns.glXMakeCurrent(primus.adpy, di.pbuffer, context);
+      primus.afns.glBindBuffer(GL_PIXEL_PACK_BUFFER_EXT, pbos[cbuf ^ 1]);
+      primus.afns.glBufferData(GL_PIXEL_PACK_BUFFER_EXT, width*height*4, NULL, GL_STREAM_READ);
+      primus.afns.glBindBuffer(GL_PIXEL_PACK_BUFFER_EXT, pbos[cbuf]);
+      primus.afns.glBufferData(GL_PIXEL_PACK_BUFFER_EXT, width*height*4, NULL, GL_STREAM_READ);
+    }
+    primus.afns.glWaitSync(di.sync, 0, GL_TIMEOUT_IGNORED);
+    primus.afns.glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+    if (!primus.sync)
+      sem_post(&di.r.relsem); // Unblock main thread as soon as possible
+    usleep(sleep_usec);
+    profiler.tick();
+    if (primus.sync == 1) // Get the previous framebuffer
+      primus.afns.glBindBuffer(GL_PIXEL_PACK_BUFFER_EXT, pbos[cbuf ^ 1]);
+    double map_time = Profiler::get_timestamp();
+    GLvoid *pixeldata = primus.afns.glMapBuffer(GL_PIXEL_PACK_BUFFER_EXT, GL_READ_ONLY);
+    map_time = Profiler::get_timestamp() - map_time;
+    sleep_usec = (map_time * 1e6 + sleep_usec) * primus.autosleep / 100;
+    profiler.tick();
+    clock_gettime(CLOCK_REALTIME, &tp);
+    tp.tv_sec  += 1;
+    if (!primus.sync && sem_timedwait(&di.d.relsem, &tp))
+      primus_warn("dropping a frame to avoid deadlock\n");
+    else
+    {
+      di.pixeldata = pixeldata;
+      sem_post(&di.d.acqsem);
+      if (primus.sync)
+      {
+       sem_wait(&di.d.relsem);
+       sem_post(&di.r.relsem); // Unblock main thread only after D::work has completed
+      }
+      cbuf ^= 1;
+      primus.afns.glBindBuffer(GL_PIXEL_PACK_BUFFER_EXT, pbos[cbuf]);
+    }
+    primus.afns.glUnmapBuffer(GL_PIXEL_PACK_BUFFER_EXT);
+    profiler.tick();
+  }
+  return NULL;
+}
+
+// Find appropriate FBConfigs on adpy for a given Visual on ddpy
+static GLXFBConfig* match_fbconfig(Display *dpy, XVisualInfo *vis)
+{
+  int ncfg, attrs[] = {
+    GLX_DOUBLEBUFFER, 0, GLX_STEREO, 0, GLX_AUX_BUFFERS, 0,
+    GLX_RED_SIZE, 0, GLX_GREEN_SIZE, 0, GLX_BLUE_SIZE, 0,
+    GLX_ALPHA_SIZE, 0, GLX_DEPTH_SIZE, 0, GLX_STENCIL_SIZE, 0,
+    GLX_ACCUM_RED_SIZE, 0, GLX_ACCUM_GREEN_SIZE, 0, GLX_ACCUM_BLUE_SIZE, 0, GLX_ACCUM_ALPHA_SIZE, 0,
+    GLX_SAMPLE_BUFFERS, 0, GLX_SAMPLES, 0, None
+  };
+  for (int i = 0; attrs[i] != None; i += 2)
+    primus.dfns.glXGetConfig(dpy, vis, attrs[i], &attrs[i+1]);
+  return primus.afns.glXChooseFBConfig(primus.adpy, 0, attrs, &ncfg);
+}
+
+GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct)
+{
+  GLXFBConfig *acfgs = match_fbconfig(dpy, vis);
+  GLXContext actx = primus.afns.glXCreateNewContext(primus.adpy, *acfgs, GLX_RGBA_TYPE, shareList, direct);
+  primus.contexts.record(actx, *acfgs, shareList);
+  return actx;
+}
+
+GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct)
+{
+  GLXContext actx = primus.afns.glXCreateNewContext(primus.adpy, config, renderType, shareList, direct);
+  primus.contexts.record(actx, config, shareList);
+  return actx;
+}
+
+GLXContext glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, GLXContext shareList, Bool direct, const int *attrib_list)
+{
+  GLXContext actx = primus.afns.glXCreateContextAttribsARB(primus.adpy, config, shareList, direct, attrib_list);
+  primus.contexts.record(actx, config, shareList);
+  return actx;
+}
+
+void glXDestroyContext(Display *dpy, GLXContext ctx)
+{
+  primus.contexts.erase(ctx);
+  // kludge: reap background tasks when deleting the last context
+  // otherwise something will deadlock during unloading the library
+  if (primus.contexts.empty())
+    for (DrawablesInfo::iterator i = primus.drawables.begin(); i != primus.drawables.end(); i++)
+      i->second.reap_workers();
+  primus.afns.glXDestroyContext(primus.adpy, ctx);
+}
+
+static GLXPbuffer create_pbuffer(DrawableInfo &di)
+{
+  int pbattrs[] = {GLX_PBUFFER_WIDTH, di.width, GLX_PBUFFER_HEIGHT, di.height, GLX_PRESERVED_CONTENTS, True, None};
+  return primus.afns.glXCreatePbuffer(primus.adpy, di.fbconfig, pbattrs);
+}
+
+// Create or recall backing Pbuffer for the drawable
+static GLXPbuffer lookup_pbuffer(Display *dpy, GLXDrawable draw, GLXContext ctx)
+{
+  if (!draw)
+    return 0;
+  bool known = primus.drawables.known(draw);
+  DrawableInfo &di = primus.drawables[draw];
+  if (!known)
+  {
+    // Drawable is a plain X Window. Get the FBConfig from the context
+    if (ctx)
+      di.fbconfig = primus.contexts[ctx].fbconfig;
+    else
+    {
+      XWindowAttributes attrs;
+      die_if(!XGetWindowAttributes(dpy, draw, &attrs), "failed to query attributes");
+      int nvis;
+      XVisualInfo tmpl = {0}, *vis;
+      tmpl.visualid = XVisualIDFromVisual(attrs.visual);
+      die_if(!(vis = XGetVisualInfo(dpy, VisualIDMask, &tmpl, &nvis)), "no visuals");
+      di.fbconfig = *match_fbconfig(dpy, vis);
+      XFree(vis);
+    }
+    di.kind = di.XWindow;
+    di.window = draw;
+    note_geometry(dpy, draw, &di.width, &di.height);
+  }
+  else if (ctx && di.fbconfig != primus.contexts[ctx].fbconfig)
+  {
+    if (di.pbuffer)
+    {
+      primus_warn("recreating incompatible pbuffer\n");
+      di.reap_workers();
+      primus.afns.glXDestroyPbuffer(primus.adpy, di.pbuffer);
+      di.pbuffer = 0;
+    }
+    di.fbconfig = primus.contexts[ctx].fbconfig;
+  }
+  if (!di.pbuffer)
+    di.pbuffer = create_pbuffer(di);
+  return di.pbuffer;
+}
+
+Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx)
+{
+  GLXPbuffer pbuffer = lookup_pbuffer(dpy, drawable, ctx);
+  tsdata.make_current(dpy, drawable, drawable);
+  return primus.afns.glXMakeCurrent(primus.adpy, pbuffer, ctx);
+}
+
+Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
+{
+  if (draw == read)
+    return glXMakeCurrent(dpy, draw, ctx);
+  GLXPbuffer pbuffer = lookup_pbuffer(dpy, draw, ctx);
+  GLXPbuffer pb_read = lookup_pbuffer(dpy, read, ctx);
+  tsdata.make_current(dpy, draw, read);
+  return primus.afns.glXMakeContextCurrent(primus.adpy, pbuffer, pb_read, ctx);
+}
+
+void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
+{
+  XFlush(dpy);
+  assert(primus.drawables.known(drawable));
+  DrawableInfo &di = primus.drawables[drawable];
+  primus.afns.glXSwapBuffers(primus.adpy, di.pbuffer);
+  if (di.kind == di.Pbuffer || di.kind == di.Pixmap)
+    return;
+  GLXContext ctx = glXGetCurrentContext();
+  if (!ctx)
+    primus_warn("glXSwapBuffers: no current context\n");
+  else if (drawable != tsdata.drawable)
+    primus_warn("glXSwapBuffers: drawable not current\n");
+  if (di.r.worker && ctx && (!di.actx || primus.contexts[di.actx].sharegroup != primus.contexts[ctx].sharegroup))
+  {
+    primus_warn("glXSwapBuffers: respawning threads after context change\n");
+    di.reap_workers();
+  }
+  if (!di.r.worker)
+  {
+    // Need to create a sharing context to use GL sync objects
+    di.actx = ctx;
+    di.d.spawn_worker(drawable, display_work);
+    di.r.spawn_worker(drawable, readback_work);
+  }
+  // Readback thread needs a sync object to avoid reading an incomplete frame
+  di.sync = primus.afns.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+  sem_post(&di.r.acqsem); // Signal the readback worker thread
+  sem_wait(&di.r.relsem); // Wait until it has issued glReadBuffer
+  primus.afns.glDeleteSync(di.sync);
+  if (di.reinit == di.RESIZE)
+  {
+    __sync_synchronize();
+    primus.afns.glXDestroyPbuffer(primus.adpy, di.pbuffer);
+    di.pbuffer = create_pbuffer(di);
+    if (ctx) // FIXME: drawable can be current in other threads
+      glXMakeContextCurrent(dpy, tsdata.drawable, tsdata.read_drawable, ctx);
+    di.r.reinit = di.reinit;
+    di.reinit = di.NONE;
+  }
+}
+
+GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, const int *attribList)
+{
+  GLXFBConfig *dconfigs = get_dconfigs(dpy);
+  GLXWindow glxwin = primus.dfns.glXCreateWindow(dpy, *dconfigs, win, attribList);
+  XFree(dconfigs);
+  DrawableInfo &di = primus.drawables[glxwin];
+  di.kind = di.Window;
+  di.fbconfig = config;
+  di.window = win;
+  note_geometry(dpy, win, &di.width, &di.height);
+  return glxwin;
+}
+
+DrawableInfo::~DrawableInfo()
+{
+  reap_workers();
+  if (pbuffer)
+    primus.afns.glXDestroyPbuffer(primus.adpy, pbuffer);
+}
+
+void glXDestroyWindow(Display *dpy, GLXWindow window)
+{
+  assert(primus.drawables.known(window));
+  primus.drawables.erase(window);
+  primus.dfns.glXDestroyWindow(dpy, window);
+}
+
+GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList)
+{
+  GLXFBConfig *dconfigs = get_dconfigs(dpy);
+  GLXPbuffer pbuffer = primus.dfns.glXCreatePbuffer(dpy, *dconfigs, attribList);
+  XFree(dconfigs);
+  DrawableInfo &di = primus.drawables[pbuffer];
+  di.kind = di.Pbuffer;
+  di.fbconfig = config;
+  for (int i = 0; attribList[i] != None; i++)
+    if (attribList[i] == GLX_PBUFFER_WIDTH)
+      di.width = attribList[i+1];
+    else if (attribList[i] == GLX_PBUFFER_HEIGHT)
+      di.height = attribList[i+1];
+  return pbuffer;
+}
+
+void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf)
+{
+  assert(primus.drawables.known(pbuf));
+  primus.drawables.erase(pbuf);
+  primus.dfns.glXDestroyPbuffer(dpy, pbuf);
+}
+
+GLXPixmap glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList)
+{
+  GLXFBConfig *dconfigs = get_dconfigs(dpy);
+  GLXPixmap glxpix = primus.dfns.glXCreatePixmap(dpy, *dconfigs, pixmap, attribList);
+  XFree(dconfigs);
+  DrawableInfo &di = primus.drawables[glxpix];
+  di.kind = di.Pixmap;
+  di.fbconfig = config;
+  note_geometry(dpy, pixmap, &di.width, &di.height);
+  return glxpix;
+}
+
+void glXDestroyPixmap(Display *dpy, GLXPixmap pixmap)
+{
+  assert(primus.drawables.known(pixmap));
+  primus.drawables.erase(pixmap);
+  primus.dfns.glXDestroyPixmap(dpy, pixmap);
+}
+
+GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *visual, Pixmap pixmap)
+{
+  GLXPixmap glxpix = primus.dfns.glXCreateGLXPixmap(dpy, visual, pixmap);
+  DrawableInfo &di = primus.drawables[glxpix];
+  di.kind = di.Pixmap;
+  note_geometry(dpy, pixmap, &di.width, &di.height);
+  GLXFBConfig *acfgs = match_fbconfig(dpy, visual);
+  di.fbconfig = *acfgs;
+  return glxpix;
+}
+
+void glXDestroyGLXPixmap(Display *dpy, GLXPixmap pixmap)
+{
+  glXDestroyPixmap(dpy, pixmap);
+}
+
+static XVisualInfo *match_visual(Display *dpy, int attrs[])
+{
+  XVisualInfo *vis = glXChooseVisual(dpy, 0, attrs);
+  for (int i = 2; attrs[i] != None && vis; i += 2)
+  {
+    int tmp = attrs[i+1];
+    primus.dfns.glXGetConfig(dpy, vis, attrs[i], &attrs[i+1]);
+    if (tmp != attrs[i+1])
+      vis = NULL;
+  }
+  return vis;
+}
+
+XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
+{
+  if (!primus.afns.glXGetVisualFromFBConfig(primus.adpy, config))
+    return NULL;
+  int i, attrs[] = {
+    GLX_RGBA, GLX_DOUBLEBUFFER,
+    GLX_RED_SIZE, 0, GLX_GREEN_SIZE, 0, GLX_BLUE_SIZE, 0,
+    GLX_ALPHA_SIZE, 0, GLX_DEPTH_SIZE, 0, GLX_STENCIL_SIZE, 0,
+    GLX_SAMPLE_BUFFERS, 0, GLX_SAMPLES, 0, None
+  };
+  for (i = 2; attrs[i] != None; i += 2)
+    primus.afns.glXGetFBConfigAttrib(primus.adpy, config, attrs[i], &attrs[i+1]);
+  XVisualInfo *vis = NULL;
+  for (i -= 2; i >= 0 && !vis; i -= 2)
+  {
+    vis = match_visual(dpy, attrs);
+    attrs[i] = None;
+  }
+  return vis;
+}
+
+int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, int attribute, int *value)
+{
+  int r = primus.afns.glXGetFBConfigAttrib(primus.adpy, config, attribute, value);
+  if (attribute == GLX_VISUAL_ID && *value)
+    return primus.dfns.glXGetConfig(dpy, glXGetVisualFromFBConfig(dpy, config), attribute, value);
+  return r;
+}
+
+void glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value)
+{
+  primus.afns.glXQueryDrawable(primus.adpy, lookup_pbuffer(dpy, draw, NULL), attribute, value);
+}
+
+void glXUseXFont(Font font, int first, int count, int list)
+{
+  unsigned long prop;
+  Display *dpy = glXGetCurrentDisplay();
+  XFontStruct *fs = XQueryFont(dpy, font);
+  XGetFontProperty(fs, XA_FONT, &prop);
+  char *xlfd = XGetAtomName(dpy, prop);
+  Font afont = XLoadFont(primus.adpy, xlfd);
+  primus.afns.glXUseXFont(afont, first, count, list);
+  XUnloadFont(primus.adpy, afont);
+  XFree(xlfd);
+  XFreeFontInfo(NULL, fs, 1);
+}
+
+GLXContext glXGetCurrentContext(void)
+{
+  return primus.afns.glXGetCurrentContext();
+}
+
+GLXDrawable glXGetCurrentDrawable(void)
+{
+  return tsdata.drawable;
+}
+
+void glXWaitGL(void)
+{
+}
+
+void glXWaitX(void)
+{
+}
+
+Display *glXGetCurrentDisplay(void)
+{
+  return tsdata.dpy;
+}
+
+GLXDrawable glXGetCurrentReadDrawable(void)
+{
+  return tsdata.read_drawable;
+}
+
+// Application sees ddpy-side Visuals, but adpy-side FBConfigs and Contexts
+XVisualInfo* glXChooseVisual(Display *dpy, int screen, int *attribList)
+{
+  return primus.dfns.glXChooseVisual(dpy, screen, attribList);
+}
+
+int glXGetConfig(Display *dpy, XVisualInfo *visual, int attrib, int *value)
+{
+  return primus.dfns.glXGetConfig(dpy, visual, attrib, value);
+}
+
+// GLX forwarders that reroute to adpy
+#define DEF_GLX_PROTO(ret, name, par, ...) \
+ret name par \
+{ return primus.afns.name(primus.adpy, __VA_ARGS__); }
+#include "glx-dpyredir.def"
+#undef DEF_GLX_PROTO
+
+// OpenGL forwarders
+#define DEF_GLX_PROTO(ret, name, par, ...) \
+void ifunc_##name(void) asm(#name) __attribute__((visibility("default"),ifunc("i" #name))); \
+extern "C" { \
+static ret l##name par \
+{ return primus.afns.name(__VA_ARGS__); } \
+static void *i##name(void) \
+{ return primus.afns.handle ? real_dlsym(primus.afns.handle, #name) : (void*)l##name; } }
+#include "gl-passthru.def"
+#undef DEF_GLX_PROTO
+
+// GLX extensions
+
+int glXSwapIntervalSGI(int interval)
+{
+  return 1; // Indicate failure to set swapinterval
+}
+
+__GLXextFuncPtr glXGetProcAddress(const GLubyte *procName)
+{
+  static const char * const redefined_names[] = {
+#define DEF_GLX_PROTO(ret, name, args, ...) #name,
+#include "glx-reimpl.def"
+#include "glxext-reimpl.def"
+#include "glx-dpyredir.def"
+#undef  DEF_GLX_PROTO
+  };
+  static const __GLXextFuncPtr redefined_fns[] = {
+#define DEF_GLX_PROTO(ret, name, args, ...) (__GLXextFuncPtr)name,
+#include "glx-reimpl.def"
+#include "glxext-reimpl.def"
+#include "glx-dpyredir.def"
+#undef  DEF_GLX_PROTO
+  };
+  enum {n_redefined = sizeof(redefined_fns) / sizeof(redefined_fns[0])};
+  // Non-GLX functions are forwarded to the accelerating libGL
+  if (memcmp(procName, "glX", 3))
+    return primus.afns.glXGetProcAddress(procName);
+  // All GLX functions are either implemented in primus or not available
+  for (int i = 0; i < n_redefined; i++)
+    if (!strcmp((const char *)procName, redefined_names[i]))
+      return redefined_fns[i];
+  return NULL;
+}
+
+__GLXextFuncPtr glXGetProcAddressARB(const GLubyte *procName)
+{
+  return glXGetProcAddress(procName);
+}
+
+static const char glxext_clientside[] = "GLX_ARB_get_proc_address ";
+static const char glxext_adpy[] = "GLX_ARB_create_context GLX_ARB_create_context_profile ";
+static const char glxext_ddpy[] = "";
+
+const char *glXGetClientString(Display *dpy, int name)
+{
+  static std::string exts(std::string(glxext_clientside) + glxext_adpy + glxext_ddpy);
+  switch (name)
+  {
+    case GLX_VENDOR: return "primus";
+    case GLX_VERSION: return "1.4";
+    case GLX_EXTENSIONS: return exts.c_str();
+    default: return NULL;
+  }
+}
+
+static std::string intersect_exts(const char *set1, const char *set2)
+{
+  std::string r;
+  for (const char *p; *set1; set1 = p + 1)
+  {
+    p = strchr(set1, ' ');
+    if (memmem(set2, strlen(set2), set1, p - set1))
+      r.append(set1, p - set1 + 1);
+  }
+  return r;
+}
+
+const char *glXQueryExtensionsString(Display *dpy, int screen)
+{
+  static std::string exts
+    (std::string(glxext_clientside)
+     + intersect_exts(glxext_adpy, primus.afns.glXQueryExtensionsString(primus.adpy, 0))
+     + intersect_exts(glxext_ddpy, primus.dfns.glXQueryExtensionsString(dpy, 0)));
+  return exts.c_str();
+}
+
+// OpenGL ABI specifies that anything above OpenGL 1.2 + ARB_multitexture must
+// be obtained via glXGetProcAddress, but some applications link against
+// extension functions, and Mesa and vendor libraries let them
+#ifndef PRIMUS_STRICT
+#warning Enabled workarounds for applications demanding more than promised by the OpenGL ABI
+
+// OpenGL extension forwarders
+#define P(name) \
+void ifunc_##name(void) asm(#name) __attribute__((visibility("default"),ifunc("i" #name))); \
+extern "C" { static void *i##name(void) \
+{ return primus.afns.handle ? real_dlsym(primus.afns.handle, #name) : NULL; } }
+#include "glext-passthru.def"
+#undef P
+#endif
diff --git a/primus.bash-completion b/primus.bash-completion
new file mode 100644 (file)
index 0000000..6d5490a
--- /dev/null
@@ -0,0 +1 @@
+have primusrun && complete -F _command primusrun
diff --git a/primusrun b/primusrun
new file mode 100755 (executable)
index 0000000..81e2dc0
--- /dev/null
+++ b/primusrun
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+# Readback-display synchronization method
+# 0: no sync, 1: D lags behind one frame, 2: fully synced
+# export PRIMUS_SYNC=${PRIMUS_SYNC:-0}
+
+# Verbosity level
+# 0: only errors, 1: warnings (default), 2: profiling
+# export PRIMUS_VERBOSE=${PRIMUS_VERBOSE:-1}
+
+# Upload/display method
+# 0: autodetect, 1: textures, 2: PBO/glDrawPixels (needs Mesa-10.1+)
+# export PRIMUS_UPLOAD=${PRIMUS_UPLOAD:-0}
+
+# Approximate sleep ratio in the readback thread, percent
+# export PRIMUS_SLEEP=${PRIMUS_SLEEP:-90}
+
+# Secondary display
+# export PRIMUS_DISPLAY=${PRIMUS_DISPLAY:-:8}
+
+# "Accelerating" libGL
+# $LIB will be interpreted by the dynamic linker
+# export PRIMUS_libGLa=${PRIMUS_libGLa:-'/usr/$LIB/nvidia/libGL.so.1'}
+
+# "Displaying" libGL
+# export PRIMUS_libGLd=${PRIMUS_libGLd:-'/usr/$LIB/libGL.so.1'}
+
+# Directory containing primus libGL
+PRIMUS_libGL=${PRIMUS_libGL:-$(dirname `readlink -ne $0`)/'$LIB'}
+
+# On some distributions, e.g. on Ubuntu, libnvidia-tls.so is not available
+# in default search paths.  Add its path manually after the primus library
+# PRIMUS_libGL=${PRIMUS_libGL}:/usr/lib/nvidia-current:/usr/lib32/nvidia-current
+
+# Mesa drivers need a few symbols to be visible
+# export PRIMUS_LOAD_GLOBAL=${PRIMUS_LOAD_GLOBAL:-'libglapi.so.0'}
+
+# Need functions from primus libGL to take precedence
+export LD_LIBRARY_PATH=${PRIMUS_libGL}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
+
+# And go!
+exec "$@"
diff --git a/primusrun.1 b/primusrun.1
new file mode 100644 (file)
index 0000000..d0bfa8e
--- /dev/null
@@ -0,0 +1,51 @@
+.TH PRIMUSRUN "1" "February 2013" "primusrun"
+.SH NAME
+primusrun \- run an application on a discrete NVIDIA video card
+.SH SYNOPSIS
+\fBprimusrun\fR \fIcommand \fR
+.SH DESCRIPTION
+Primus implements low-overhead local-only client-side OpenGL offloading via
+GLX forking.
+.sp
+It is currently intended to be used alongside Bumblebee and provides a
+drop-in replacement for optirun (i.e. "primusrun").
+.SH VARIABLES
+The following is a list of environment variables affecting primus library that
+may be relevant for end users:
+.IP "\s-1PRIMUS_SYNC\s0" 4
+Readback-display synchronization method (default: 0)
+.br
+0: no sync, 1: synced, display previous frame, 2: synced, display latest frame
+.IP "\s-1PRIMUS_VERBOSE\s0" 4
+Verbosity level (default: 1)
+.br
+0: only errors, 1: warnings, 2: profiling
+.IP "\s-1PRIMUS_DISPLAY\s0" 4
+The secondary Xorg server display number (default: :8)
+.SH EXAMPLES
+.TP
+\fBprimusrun glxgears \-info\fR
+Runs the graphics demo supplied by mesa-utils to confirm whether the
+discrete card is being used for GL rendering.
+.TP
+\fBPRIMUS_VERBOSE=2 primusrun glxgears\fR
+Runs the graphics demo supplied by mesa-utils with verbose output from primus.
+.TP
+\fBvblank_mode=0 primusrun glxgears\fR
+Disable vblank synchronisation, typically used for benchmarking purposes.
+.SH ISSUES
+Since compositing hurts performance, invoking primus when a compositing WM
+is active is not recommended. If you need to use primus with compositing and
+see flickering or bad performance, synchronizing primus' display thread with
+the application's rendering thread may help.
+.sp
+\fBPRIMUS_SYNC=1 primusrun ...\fR
+.sp
+This makes primus display the previously rendered frame. Alternatively, with
+PRIMUS_SYNC=2 primus will display the latest rendered frame, trading frame
+rate for reduced visual latency.
+.SH AUTHOR
+Primus was created by Alexander Monakov <amonakov@gmail.com>.
+.PP
+This manual page was written by Vincent Cheng <Vincentc1208@gmail.com>,
+for the Debian project (and may be used by others).
diff --git a/technotes.md b/technotes.md
new file mode 100644 (file)
index 0000000..eb6d75c
--- /dev/null
@@ -0,0 +1,180 @@
+Notes on primus implementation
+==============================
+
+primus: quick'n'dirty OpenGL offloading
+
+The purpose is to redirect OpenGL rendering to another X display, and copy
+the rendered frames to the original (as if rendering was not redirected),
+similar to VirtualGL, but with different assumptions and design goals.
+
+primus makes the following assumptions:
+
+* both X servers are local, and direct rendering is available on both
+* the application is "well-behaved" (uses double buffering, does not use
+  color index rendering, does not draw on top of the OpenGL drawable, etc.)
+
+In contrast, VirtualGL:
+
+* assumes that the application's X display is remote
+* supports obscure OpenGL functionality, making it more versatile
+
+The design goals are:
+
+* simplicity/minimalism:
+    - only GLX functions are overridden
+    - only two Xlib functions are used
+* efficiency:
+    - minimal amount of framebuffer data copying achievable from
+      application-level offloading (unfortunately OpenGL does
+      not allow to reduce beyond 2 copies, readback+display)
+    - pipelining of rendering, readback and display
+
+Put another way, VirtualGL is optimized for running arbitrary OpenGL
+applications over a network, with correctness and bandwidth being primary
+concerns, while primus is optimized for running modern games on hybrid
+graphics hardware setups, with simplicity and performance in mind.  It is only
+needed until DMA-BUF/PRIME offloading is implemented and mature.
+
+This document collects various interesting issues encountered while
+implementing primus.
+
+Assuming that a secondary X server driving the rendering slave card is
+present, OpenGL offloading can be achieved by intercepting GLX calls to
+reroute application's rendering to a pbuffer on the secondary X server, and
+then reading back the framebuffer and displaying it on the original drawable.
+
+Intercepting GLX calls
+----------------------
+
+The usual way to perform symbol interposition in Linux is to use LD_PRELOAD,
+and that is what VirtualGL does.  However, that is not enough when an
+application uses dlopen+dlsym to access library functions. To support that,
+VirtualGL overrides dlopen and dlsym via LD_PRELOAD as well, and it even
+intercepts `dlopen("libdl")`. Perhaps a cleaner approach is to make the
+wrapper provide the complete API (GLX+OpenGL in this case) and add the wrapper
+into LD_LIBRARY_PATH instead, which is what primus implements. One problem
+with this approach is that although primus overrides only GLX functions, it
+has to implement trivial forwarding for OpenGL functions.
+
+If the underlying OpenGL library is compiled without -Bsymbolic and calls
+GLX functions itself, those calls will invoke functions from the wrapper,
+which will cause failures unless the wrapper is prepared for that by keeping a
+per-thread boolean value indicating whether a wrapper function was entered but
+not returned yet (primus does not do that yet).
+
+Implementing GLX redirection
+----------------------------
+
+For each rendering context created by the application, primus creates an
+additional slave-side context for readback and master-side context for display
+(the latter would not be necessary if displaying the framebuffer was performed
+by some other means than OpenGL, but it's useful for vblank synchronization).
+
+For each application thread that calls glXMakeCurrent, primus additionally
+spawns a readback thread and a display thread. Rendering, readback and display
+are pipelined: application thread regains control as soon as readback thread
+issued an asynchronous glReadPixels into a PBO, and readback thread uses two
+PBOs to perform readback of a new frame into one while another is used by the
+display thread.
+
+Threads signal data availability/release via posix semaphores. Additionally, a
+GL sync object is required so that readback thread does not read an incomplete
+frame.
+
+The application sees slave-side FBConfig and GLXContext IDs, but master-side X
+Visuals. 
+
+One GLX function that is not easily redirected is glXUseXFont, as it internally
+calls OpenGL functions on bitmap data from the X server. We need bitmap data
+from one server, but OpenGL functions need to be called in the other server's
+context.
+
+Direct Rendering on Both Servers
+--------------------------------
+
+The worker threads each get a direct rendering context. One small issue that
+was encountered is that symbols from libglapi.so need to be loaded by primus
+in a global namespace (`dlopen("libglapi.so.0", RTLD_GLOBAL)`), otherwise DRI
+modules would fail to load (they need symbols from libglapi, but don't link
+against it). Starting with Mesa 9.0, DRI modules do link against libglapi, so
+this is not a problem.
+
+However, this means that without shared libglapi, it is not possible to obtain
+direct rendering context when loading Mesa with `dlopen("libGL.so.1",
+RTLD_LOCAL)`.    
+
+Xlib and threads
+----------------
+
+primus spawns additional threads for each application thread that calls
+glXMakeCurrent: a readback thread and a display thread. The latter makes calls
+to glXSwapBuffers after drawing a full-screen quad asynchronously with the
+application. Initially, primus called XInitThreads to enable that, as
+suggested by the Xlib error message. However, if an applications loads both
+Xlib and libGL dynamically via dlopen, primus may not be able to call
+XInitThreads early enough. It turned out that opening separate X connections
+for primus' needs is a simpler and more robust solution.
+
+Forwarding OpenGL calls
+-----------------------
+
+To provide OpenGL API functions, primus contains trivial forwarding functions
+(VirtualGL overrides some of OpenGL functions, e.g. glFinish to support
+single-buffered applications; primus does not support those). However, it
+would be better to rely on a dynamic linker mechanism to avoid the need to
+provide forwarder implementations, and instead make the dynamic linker resolve
+OpenGL functions to definitions found in a slave libGL. On Solaris, that would
+be possible with per-symbol DT_FILTER tagging; unfortunately, this is not
+supported in binutils and glibc.
+
+Another question is what functions need to be forwarded. Per OpenGL ABI
+document, libraries need to export only up to OpenGL 1.2 and ARB_multitexture,
+and anything above that the applications must obtain via glXGetProcAddress. In
+reality, Mesa's libGL and nVidia's libGL export a significant (but different)
+amount of functions implementing extensions, and there are applications either
+linking against those (fortunately not many, Braid and Trine 2 have been found
+guilty so far) or even trying to obtain pointers via dlsym (Enemy Territory).
+
+Compositing
+-----------
+
+There had been reports that using primus under a compositing WM causes
+flickering or slow/uneven update rate.  When worker threads are synchronized
+in a way that the application's thread calling glXSwapBuffers does not regain
+control until the display worker completed blitting and called glXSwapBuffers
+itself, those issues are not observed. It's unclear what mechanism is causing
+the problem.
+
+Waiting for the display worker to finish completely serializes
+render-readback-display, so may cause a big degradation in performance. The
+recommended mode is to make the display worker display the previously rendered
+frame: this should achieve better performance at the expense of latency of
+presentation (and black first frame unless special care is given).
+
+
+Window Resizing 
+---------------
+
+It is not obvious how to receive notifications of window resizing in primus.
+At the moment, it simply calls XGetGeometry every frame (without that, the
+only Xlib function called in primus would be XOpenDisplay).  VirtualGL
+intercepts several resizing-related functions from Xlib, and additionally
+tries to deduce drawable size from glViewport calls.
+
+Window Destruction 
+------------------
+
+Since display worker runs asynchronously by default, there is a problem that
+the window it is drawing to may be destroyed after application regained
+control after calling glXSwapBuffers, but before the display worker completed
+drawing and called glXSwapBuffers itself. The worker then encounters an X
+error and causes the application to terminate. This problem does not arise
+when worker threads are synchronized as described above.  How to avoid this
+problem while still running the display worker asynchronously?
+
+Multilib
+--------
+
+Linux dynamic linker expands $LIB in paths according to current architecture
+(since 2002).  This nice feature is used both in dlopen() calls in primus and
+the wrapper script.