summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2013-09-19 09:50:49 -0700
committerEric Anholt <eric@anholt.net>2013-10-16 11:43:11 -0700
commita909eb4a229ebbea2d60717e748df3f0a2f69cc4 (patch)
treeb2b265d8609bd52369b4b6345ebc8d07f72d1e0e
parentdb667aa8b847aa9718bce8f371c65a739ea922ef (diff)
Add the generator and build infrastructure.
Not actually working yet, but it's a snapshot to start from.
-rw-r--r--.gitignore90
-rw-r--r--Makefile.am36
-rw-r--r--README.md61
-rwxr-xr-xautogen.sh14
-rw-r--r--configure.ac75
-rw-r--r--epoxy.pc.in10
-rw-r--r--include/epoxy/gl.h52
-rw-r--r--include/epoxy/gl_common.h38
-rw-r--r--include/epoxy/glx.h51
-rw-r--r--include/epoxy/glx_common.h38
-rw-r--r--src/Makefile.am84
-rw-r--r--src/dispatch_common.c217
-rw-r--r--src/dispatch_common.h55
-rwxr-xr-xsrc/gen_dispatch.py456
14 files changed, 1277 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..35b14ca
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,90 @@
+#
+# X.Org module default exclusion patterns
+# The next section if for module specific patterns
+#
+# Do not edit the following section
+# GNU Build System (Autotools)
+aclocal.m4
+autom4te.cache/
+autoscan.log
+ChangeLog
+compile
+config.guess
+config.h
+config.h.in
+config.log
+config-ml.in
+config.py
+config.status
+config.status.lineno
+config.sub
+configure
+configure.scan
+depcomp
+.deps/
+INSTALL
+install-sh
+.libs/
+libtool
+libtool.m4
+ltmain.sh
+lt~obsolete.m4
+ltoptions.m4
+ltsugar.m4
+ltversion.m4
+Makefile
+Makefile.in
+mdate-sh
+missing
+mkinstalldirs
+*.pc
+py-compile
+stamp-h?
+symlink-tree
+texinfo.tex
+ylwrap
+src/sna/git_version.h
+src/sna/brw/brw_test
+
+# Do not edit the following section
+# Edit Compile Debug Document Distribute
+*~
+*.[0-9]
+*.[0-9]x
+*.bak
+*.bin
+core
+*.dll
+*.exe
+*-ISO*.bdf
+*-JIS*.bdf
+*-KOI8*.bdf
+*.kld
+*.ko
+*.ko.cmd
+*.lai
+*.l[oa]
+*.[oa]
+*.obj
+*.patch
+*.so
+*.pcf.gz
+*.pdb
+*.tar.bz2
+*.tar.gz
+#
+# Add & Override patterns for gldispatch
+#
+# Edit the following section as needed
+# For example, !report.pc overrides *.pc. See 'man gitignore'
+#
+configure.lineno
+.dirstamp
+
+gl_generated_dispatch.c
+gl_generated.h
+gl_generated_vtable_defines.h
+
+glx_generated_dispatch.c
+glx_generated.h
+glx_generated_vtable_defines.h
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..3d8179b
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,36 @@
+# Copyright 2005 Adam Jackson.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+SUBDIRS = src
+
+#if HAVE_X11
+#SUBDIRS += test
+#endif
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = epoxy.pc
+
+EXTRA_DIST = \
+ epoxy.pc.in \
+ registry/egl.xml \
+ registry/gl.xml \
+ registry/glx.xml \
+ registry/wgl.xml \
+ $()
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c5f36b2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,61 @@
+Epoxy is a library for handling OpenGL function pointer management for
+you.
+
+It hides the complexity of dlopen(), dlsym(), glXGetProcAddress(),
+eglGetProcAddress(), etc. from the app developer, with very little
+knowledge needed on their part. Just read your GL specs and write
+code using undecorated function names like glCompileShader().
+
+Don't forget to check for your extensions or versions being present
+before you use them, just like before! We'll tell you what you forgot
+to check for instead of just segfaulting, though.
+
+Why does this library exist?
+----------------------------
+
+OpenGL on Linux (and other platforms) made some ABI decisions back in
+the days when symbol versioning and dlsym() weren't as widely
+available, that resulted in window-systems-specific APIs that looked
+kind of like dlsym. They allowed you to build an app that required
+OpenGL 1.2, but could optionally use features of OpenGL 1.4 if the
+implementation made those available through the glXGetProcAddress()
+(or other similarly-named) mechanism.
+
+The downside is that the fixed OpenGL 1.2 ABI means that application
+developers have to GetProcAddress() out every modern GL entrypoint
+they want to use and stash that function pointer somewhere. Sometimes
+this is done in a pretty way (like libGLEW), sometimes it is done in
+an ad-hoc way (like most applications I've seen), but it's never done
+as well as we think it could be done.
+
+Additionally, the proliferation of OpenGL ABIs (desktop GL, GLESv1,
+GLESv2) and window systems (GLX, AGL, WGL, all versus EGL) means that
+
+Switching your code to using epoxy
+----------------------------------
+
+It should be as easy as replacing:
+
+> #include <GL/gl.h>
+> #include <GL/glx.h>
+> #include <GL/glext.h>
+
+with:
+
+> #include <epoxy/gl.h>
+> #include <epoxy/glx.h>
+
+Additionally, some new helpers become available, so you don't have to
+write them:
+
+int epoxy_gl_version() returns the GL version:
+
+12 for GL 1.2
+20 for GL 2.0
+44 for GL 4.4
+
+bool epoxy_has_gl_extension() returns whether a GL extension is
+available ("GL_ARB_texture_buffer_object", for example).
+
+Note that this is not terribly fast, so keep it out of your hot paths,
+ok?
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..fc34bd5
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+if test -z "$NOCONFIGURE"; then
+ $srcdir/configure "$@"
+fi
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..f2f137f
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,75 @@
+# Copyright © 2013 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+# Initialize Autoconf
+AC_PREREQ([2.60])
+AC_INIT([libepoxy],
+ [1.0],
+ [https://people.freedesktop.org/~anholt/libepoxy],
+ [libepoxy])
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_HEADERS([config.h])
+
+# Initialize Automake
+AM_INIT_AUTOMAKE([foreign dist-bzip2 subdir-objects])
+
+# Require X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS
+m4_ifndef([XORG_MACROS_VERSION],
+ [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen.
+ Hint: either install from source, git://anongit.freedesktop.org/xorg/util/macros or,
+ depending on you distribution, try package 'xutils-dev' or 'xorg-x11-util-macros'])])
+
+XORG_MACROS_VERSION(1.8)
+XORG_DEFAULT_OPTIONS
+
+AC_CHECK_PROGS([PYTHON], [python3 python2 python])
+
+# Initialize libtool
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+AC_SYS_LARGEFILE
+
+if test "x$GCC" = xyes; then
+ save_CFLAGS="$CFLAGS"
+ AC_MSG_CHECKING([whether $CC supports -fvisibility=hidden])
+ VISIBILITY_CFLAGS="-fvisibility=hidden"
+ CFLAGS="$CFLAGS $VISIBILITY_CFLAGS"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM()], AC_MSG_RESULT([yes]),
+ [VISIBILITY_CFLAGS=""; AC_MSG_RESULT([no])]);
+
+ # Restore CFLAGS; VISIBILITY_CFLAGS are added to it where needed.
+ CFLAGS=$save_CFLAGS
+fi
+
+AC_SUBST([VISIBILITY_CFLAGS])
+
+PKG_CHECK_MODULES(X11, [x11], [x11=yes], [x11=no])
+AM_CONDITIONAL(HAVE_X11, test x$x11 = xyes)
+
+
+AC_CONFIG_FILES([
+ epoxy.pc
+ Makefile
+ src/Makefile
+])
+AC_OUTPUT
+
+echo " PYTHON: $PYTHON"
diff --git a/epoxy.pc.in b/epoxy.pc.in
new file mode 100644
index 0000000..6d484d1
--- /dev/null
+++ b/epoxy.pc.in
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: epoxy
+Description: epoxy GL dispatch Library
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lepoxy
diff --git a/include/epoxy/gl.h b/include/epoxy/gl.h
new file mode 100644
index 0000000..2b3bbaf
--- /dev/null
+++ b/include/epoxy/gl.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/** @file gl.h
+ *
+ * Provides an implementation of a GL dispatch layer using a hidden
+ * vtable.
+ *
+ * This is a lower performance path than ifuncs when they are
+ * available, but it is required if you might have multiple return
+ * values for GetProcAddress/dlsym()ed functions. That is the case if
+ * you're using WGL (which can return different function pointers per
+ * context), or if you dlclose() and re-dlopen() libGL (which means
+ * you'll get different dynamically allocated dispatch stubs).
+ */
+
+#ifndef __EPOXY_GL_H
+#define __EPOXY_GL_H
+
+#if defined(__gl_h_) || defined(__glext_h_)
+#error epoxy/gl.h must be included before (or in place of) GL/gl.h
+#else
+#define __gl_h_
+#define __glext_h_
+#endif
+
+
+#include "epoxy/gl_common.h"
+#include "epoxy/gl_generated.h"
+#include "epoxy/gl_generated_vtable_defines.h"
+
+#endif /* __EPOXY_GL_H */
diff --git a/include/epoxy/gl_common.h b/include/epoxy/gl_common.h
new file mode 100644
index 0000000..991fe98
--- /dev/null
+++ b/include/epoxy/gl_common.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/** @file gl_common.h
+ *
+ * Provides prototypes for epoxy GL functions independent of dispatch mechanism.
+ */
+
+#ifndef EPOXY_GL_COMMON_H
+#define EPOXY_GL_COMMON_H
+
+#include <stdbool.h>
+
+bool epoxy_has_gl_extension(const char *extension);
+int epoxy_gl_version(void);
+
+#endif /* EPOXY_GL_COMMON_H */
+
diff --git a/include/epoxy/glx.h b/include/epoxy/glx.h
new file mode 100644
index 0000000..215cd2a
--- /dev/null
+++ b/include/epoxy/glx.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/** @file glx.h
+ *
+ * Provides an implementation of a GLX dispatch layer using a hidden
+ * vtable.
+ *
+ * This is a lower performance path than ifuncs when they are
+ * available, but it is required if you might have multiple return
+ * values for GetProcAddress/dlsym()ed functions (for example, if you
+ * unload libGL.so.1).
+ */
+
+#ifndef __EPOXY_GLX_H
+#define __EPOXY_GLX_H
+
+#if defined(__glx_h_) || defined(__glxext_h_)
+#error epoxy/glx.h must be included before (or in place of) GL/glx.h
+#else
+#define __glext_h_
+#define __glxext_h_
+#endif
+
+#pragma once
+
+#include "epoxy/glx_common.h"
+#include "epoxy/glx_generated.h"
+#include "epoxy/glx_generated_vtable_defines.h"
+
+#endif /* __EPOXY_GLX_H */
diff --git a/include/epoxy/glx_common.h b/include/epoxy/glx_common.h
new file mode 100644
index 0000000..cee9f51
--- /dev/null
+++ b/include/epoxy/glx_common.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/** @file gl_common.h
+ *
+ * Provides prototypes for epoxy GL functions independent of dispatch mechanism.
+ */
+
+#ifndef EPOXY_GLX_COMMON_H
+#define EPOXY_GLX_COMMON_H
+
+#include <stdbool.h>
+
+bool epoxy_has_glx_extension(const char *extension);
+int epoxy_glx_version(void);
+
+#endif /* EPOXY_GLX_COMMON_H */
+
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..6719397
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,84 @@
+# Copyright 2005 Adam Jackson.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# on the rights to use, copy, modify, merge, publish, distribute, sub
+# license, and/or sell copies of the Software, and to permit persons to whom
+# the Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+# ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/include \
+ $()
+
+AM_CFLAGS = $(CWARNFLAGS) $(VISIBILITY_CFLAGS)
+
+epoxyincludedir = $(includedir)/epoxy
+lib_LTLIBRARIES = libepoxy.la
+
+epoxyinclude_DATA = \
+ $(GL_INCLUDES) \
+ $(GLX_INCLUDES) \
+ $()
+
+GL_INCLUDES = \
+ ../include/epoxy/gl.h \
+ ../include/epoxy/gl_common.h \
+ $(GENERATED_GL_INCLUDES) \
+ $()
+
+GLX_INCLUDES = \
+ ../include/epoxy/glx.h \
+ ../include/epoxy/glx_common.h \
+ $(GENERATED_GLX_INCLUDES) \
+ $()
+
+GENERATED_GL_INCLUDES = \
+ $(builddir)/../include/epoxy/gl_generated.h \
+ $(builddir)/../include/epoxy/gl_generated_vtable_defines.h \
+ $()
+
+GENERATED_GLX_INCLUDES = \
+ $(builddir)/../include/epoxy/glx_generated.h \
+ $(builddir)/../include/epoxy/glx_generated_vtable_defines.h \
+ $()
+
+GENERATED_GL = \
+ $(builddir)/gl_generated_dispatch.c \
+ $(GENERATED_GL_INCLUDES) \
+ $()
+
+GENERATED_GLX = \
+ $(builddir)/glx_generated_dispatch.c \
+ $(GENERATED_GLX_INCLUDES) \
+ $()
+
+BUILT_SOURCES = \
+ $(GENERATED_GL) \
+ $(GENERATED_GLX) \
+ $()
+CLEANFILES = $(BUILT_SOURCES)
+
+libepoxy_la_SOURCES = \
+ dispatch_common.c \
+ dispatch_common.h \
+ $(BUILT_SOURCES)
+ $()
+
+$(GENERATED_GL): gen_dispatch.py ../registry/gl.xml
+ $(AM_V_GEN)$(PYTHON) gen_dispatch.py --dir $(top_builddir) ../registry/gl.xml
+
+$(GENERATED_GLX): gen_dispatch.py ../registry/glx.xml
+ $(AM_V_GEN)$(PYTHON) gen_dispatch.py --dir $(top_builddir) ../registry/glx.xml
diff --git a/src/dispatch_common.c b/src/dispatch_common.c
new file mode 100644
index 0000000..1b45389
--- /dev/null
+++ b/src/dispatch_common.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/**
+ * @file dispatch_common.c
+ *
+ * Implements common code shared by the generated GL/EGL/GLX dispatch code.
+ *
+ * A collection of some important specs on getting GL function pointers.
+ *
+ * From the linux GL ABI (http://www.opengl.org/registry/ABI/):
+ *
+ * "3.4. The libraries must export all OpenGL 1.2, GLU 1.3, GLX 1.3, and
+ * ARB_multitexture entry points statically.
+ *
+ * 3.5. Because non-ARB extensions vary so widely and are constantly
+ * increasing in number, it's infeasible to require that they all be
+ * supported, and extensions can always be added to hardware drivers
+ * after the base link libraries are released. These drivers are
+ * dynamically loaded by libGL, so extensions not in the base
+ * library must also be obtained dynamically.
+ *
+ * 3.6. To perform the dynamic query, libGL also must export an entry
+ * point called
+ *
+ * void (*glXGetProcAddressARB(const GLubyte *))();
+ *
+ * The full specification of this function is available separately. It
+ * takes the string name of a GL or GLX entry point and returns a pointer
+ * to a function implementing that entry point. It is functionally
+ * identical to the wglGetProcAddress query defined by the Windows OpenGL
+ * library, except that the function pointers returned are context
+ * independent, unlike the WGL query."
+ *
+ * From the EGL 1.4 spec:
+ *
+ * "Client API function pointers returned by eglGetProcAddress are
+ * independent of the display and the currently bound client API context,
+ * and may be used by any client API context which supports the extension.
+ *
+ * eglGetProcAddress may be queried for all of the following functions:
+ *
+ * • All EGL and client API extension functions supported by the
+ * implementation (whether those extensions are supported by the current
+ * client API context or not). This includes any mandatory OpenGL ES
+ * extensions.
+ *
+ * eglGetProcAddress may not be queried for core (non-extension) functions
+ * in EGL or client APIs 20 .
+ *
+ * For functions that are queryable with eglGetProcAddress,
+ * implementations may choose to also export those functions statically
+ * from the object libraries im- plementing those functions. However,
+ * portable clients cannot rely on this behavior.
+ *
+ * From the GLX 1.4 spec:
+ *
+ * "glXGetProcAddress may be queried for all of the following functions:
+ *
+ * • All GL and GLX extension functions supported by the implementation
+ * (whether those extensions are supported by the current context or
+ * not).
+ *
+ * • All core (non-extension) functions in GL and GLX from version 1.0 up
+ * to and including the versions of those specifications supported by
+ * the implementation, as determined by glGetString(GL VERSION) and
+ * glXQueryVersion queries."
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <stdio.h>
+#include "epoxy/gl.h"
+#include "epoxy/glx.h"
+#include "dispatch_common.h"
+
+/* XXX: Make this thread local */
+struct api local_api;
+
+struct api *api = &local_api;
+
+bool
+epoxy_is_desktop_gl(void)
+{
+ const char *es_prefix = "OpenGL ES ";
+ const char *version = (const char *)glGetString(GL_VERSION);
+
+ printf("VERSION %s\n", version);
+ return !strncmp(es_prefix, version, strlen(es_prefix));
+}
+
+PUBLIC int
+epoxy_gl_version(void)
+{
+ GLint major, minor;
+
+ glGetIntegerv(GL_MAJOR_VERSION, &major);
+ glGetIntegerv(GL_MAJOR_VERSION, &minor);
+
+ return major * 10 + minor;
+}
+
+bool
+epoxy_is_glx(void)
+{
+ return true; /* XXX */
+}
+
+int
+epoxy_glx_version(void)
+{
+ return 14; /* XXX */
+}
+
+static bool
+epoxy_extension_in_string(const char *extension_list, const char *ext)
+{
+ const char *ptr = extension_list;
+ int len = strlen(ext);
+
+ /* Make sure that don't just find an extension with our name as a prefix. */
+ do {
+ ptr = strstr(ptr, ext);
+ } while (ptr && (ptr[len] != ' ' && ptr[len] != 0));
+
+ return ptr != NULL;
+}
+
+PUBLIC bool
+epoxy_has_gl_extension(const char *ext)
+{
+ return epoxy_extension_in_string((const char *)glGetString(GL_EXTENSIONS),
+ ext);
+}
+
+#if 0
+PUBLIC bool
+epoxy_has_egl_extension(const char *ext)
+{
+ return epoxy_extension_in_string(eglQueryString(EGL_EXTENSIONS), ext);
+}
+#endif
+
+PUBLIC bool
+epoxy_has_glx_extension(const char *ext)
+{
+ Display *dpy = glXGetCurrentDisplay();
+ int screen = 0;
+
+ if (!dpy) {
+ fprintf(stderr, "waffle needs a display!"); /* XXX */
+ return false;
+ }
+
+ /* No, you can't just use glXGetClientString or glXGetServerString() here.
+ * Those each tell you about one half of what's needed for an extension to
+ * be supported, and glXQueryExtensionsString().
+ */
+ return epoxy_extension_in_string(glXQueryExtensionsString(dpy, screen), ext);
+}
+
+void *
+epoxy_dlsym(const char *name)
+{
+ assert(api->gl_handle);
+ return dlsym(api->gl_handle, name);
+}
+
+void *
+epoxy_get_proc_address(const char *name)
+{
+ return glXGetProcAddress((const GLubyte *)name);
+}
+
+void
+epoxy_glx_autoinit(void)
+{
+ if (api->gl_handle)
+ return;
+
+ api->gl_handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
+ if (!api->gl_handle) {
+ fprintf(stderr, "Couldn't open libGL.so.1: %s", dlerror());
+ exit(1);
+ }
+
+ api->winsys_handle = api->gl_handle;
+}
+
+void
+epoxy_platform_autoinit(void)
+{
+ epoxy_glx_autoinit();
+}
+
diff --git a/src/dispatch_common.h b/src/dispatch_common.h
new file mode 100644
index 0000000..0113e8f
--- /dev/null
+++ b/src/dispatch_common.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include "epoxy/gl_common.h"
+#include "epoxy/glx_common.h"
+
+#ifndef PUBLIC
+# if (defined(__GNUC__) && __GNUC__ >= 4) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
+# define PUBLIC __attribute__((visibility("default")))
+# else
+# define PUBLIC
+# endif
+#endif
+
+struct api {
+ bool is_glx;
+ bool is_gl;
+ bool is_gles1;
+ bool is_gles2; /**< Also GLES3 */
+
+ /** dlopen() return value for libGL.so.1, libGLESv2.so.1, etc. */
+ void *gl_handle;
+
+ /** dlopen() return value for libGL.so.1 or libEGL.so.1 */
+ void *winsys_handle;
+};
+
+bool epoxy_is_desktop_gl(void);
+bool epoxy_is_glx(void);
+
+void *epoxy_get_proc_address(const char *name);
+void *epoxy_dlsym(const char *name);
+void epoxy_glx_autoinit(void);
+void epoxy_platform_autoinit(void);
diff --git a/src/gen_dispatch.py b/src/gen_dispatch.py
new file mode 100755
index 0000000..5adc57d
--- /dev/null
+++ b/src/gen_dispatch.py
@@ -0,0 +1,456 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Copyright © 2013 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+import sys
+import argparse
+import xml.etree.ElementTree as ET
+import re
+import os
+
+class GLFunction(object):
+ def __init__(self, ret_type, name):
+ self.name = name
+ self.ptr_type = 'PFN' + name.upper()
+ self.ret_type = ret_type
+ self.providers = []
+ self.args = []
+ self.args_list = ''
+ self.args_decl = 'void'
+
+ # For an alias group, alias_func is the function they are all
+ # marked as the alias of.
+ self.alias_func = None
+ # For an alias group, the shared alias_func has this list of
+ # functions (of different names) that are marked as aliases of
+ # it, so that it can write a resolver for all of them.
+ self.alias_exts = []
+
+ def add_arg(self, type, name):
+ self.args.append((type, name))
+ if self.args_decl == 'void':
+ self.args_list = name
+ self.args_decl = type + ' ' + name
+ else:
+ self.args_list += ', ' + name
+ self.args_decl += ', ' + type + ' ' + name
+
+ def add_provider(self, condition, loader, human_name):
+ self.providers.append((condition, loader, human_name))
+
+ def add_alias(self, ext):
+ # We don't support transitivity of aliases.
+ assert not ext.alias_exts
+ assert self.alias_func is None
+
+ self.alias_exts.append(ext)
+ ext.alias_func = self
+
+class Generator(object):
+ def __init__(self):
+ self.enums = {}
+ self.functions = {}
+ self.max_enum_name_len = 1
+ self.copyright_comment = None
+ self.typedefs = ''
+ self.out_file = None
+
+ self.dlsym_loader = 'epoxy_dlsym("{0}")'
+ self.gpa_loader = 'epoxy_get_proc_address("{0}")'
+
+ def all_text_until_element_name(self, element, element_name):
+ text = ''
+
+ if element.text is not None:
+ text += element.text
+
+ for child in element:
+ if child.tag == element_name:
+ break
+ if child.text:
+ text += child.text
+ if child.tail:
+ text += child.tail
+ return text
+
+ def out(self, text):
+ self.out_file.write(text)
+
+ def outln(self, text):
+ self.out_file.write(text + '\n')
+
+ def parse_typedefs(self, reg):
+ for t in reg.findall('types/type'):
+ if 'name' in t.attrib and t.attrib['name'] not in {'GLhandleARB'}:
+ continue
+
+ if t.text is not None:
+ self.typedefs += t.text
+
+ for child in t:
+ if child.text:
+ self.typedefs += child.text
+ if child.tail:
+ self.typedefs += child.tail
+ self.typedefs += '\n'
+
+ def parse_enums(self, reg):
+ for enum in reg.findall('enums/enum'):
+ name = enum.get('name')
+ self.max_enum_name_len = max(self.max_enum_name_len, len(name))
+ self.enums[name] = enum.get('value')
+
+ def get_function_return_type(self, proto):
+ # Everything up to the start of the name element is the return type.
+ return self.all_text_until_element_name(proto, 'name').strip()
+
+ def parse_function_definitions(self, reg):
+ for command in reg.findall('commands/command'):
+ proto = command.find('proto')
+ name = proto.find('name').text
+ ret_type = self.get_function_return_type(proto)
+
+ func = GLFunction(ret_type, name)
+
+ for arg in command.findall('param'):
+ func.add_arg(self.all_text_until_element_name(arg, 'name').strip(),
+ arg.find('name').text)
+
+ alias = command.find('alias')
+ if alias is not None:
+ alias_func = self.functions[alias.get('name')]
+ alias_func.add_alias(func)
+
+ self.functions[name] = func
+
+ def drop_weird_glx_functions(self):
+ # Drop a few ancient SGIX GLX extensions that use types not defined
+ # anywhere in Xlib. In glxext.h, they're protected by #ifdefs for the
+ # headers that defined them.
+ weird_functions = [name for name, func in self.functions.items()
+ if 'VLServer' in func.args_decl
+ or 'DMparams' in func.args_decl]
+
+ for name in weird_functions:
+ del self.functions[name]
+
+ def process_require_statements(self, feature, condition, loader, human_name):
+ for command in feature.findall('require/command'):
+ name = command.get('name')
+ func = self.functions[name]
+ func.add_provider(condition, loader.format(name), human_name)
+
+ def parse_function_providers(self, reg):
+ for feature in reg.findall('feature'):
+ api = feature.get('api') # string gl, gles1, gles2, glx
+ m = re.match('([0-9])\.([0-9])', feature.get('number'))
+ version = int(m.group(1)) * 10 + int(m.group(2))
+
+ if api == 'gl':
+ human_name = 'Desktop OpenGL {0}'.format(feature.get('number'))
+ condition = 'epoxy_is_desktop_gl()'
+
+ # Everything in GL 1.2 is guaranteed to be present as
+ # public symbols in the Linux libGL ABI. Everything
+ # else is supposed to not be present, so you have to
+ # glXGetProcAddress() it.
+ if version <= 12:
+ loader = self.dlsym_loader
+ else:
+ loader = self.gpa_loader
+ condition += ' && epoxy_gl_version() >= {0}'.format(version)
+ elif api == 'gles2':
+ human_name = 'OpenGL ES {0}'.format(feature.get('number'))
+ condition = '!epoxy_is_desktop_gl() && epoxy_gl_version() >= {0}'.format(version)
+
+ if version <= 20:
+ loader = self.dlsym_loader
+ else:
+ loader = self.gpa_loader
+ elif api == 'gles1':
+ human_name = 'OpenGL ES 1.0'
+ condition = '!epoxy_is_desktop_gl() && epoxy_gl_version() == 10'
+
+ if version <= 20:
+ loader = self.dlsym_loader
+ else:
+ loader = self.gpa_loader
+ elif api == 'glx':
+ human_name = 'GLX {0}'.format(version)
+ condition = 'epoxy_glx_version() >= {0}'.format(version)
+ loader = self.dlsym_loader
+
+ if version <= 13:
+ loader = self.dlsym_loader
+ else:
+ loader = self.gpa_loader
+ else:
+ sys.exit('unknown API: "{0}"'.format(api))
+
+ self.process_require_statements(feature, condition, loader, human_name)
+
+ for extension in reg.findall('extensions/extension'):
+ extname = extension.get('name')
+ # 'supported' is a set of strings like gl, gles1, gles2, or glx, which are
+ # separated by '|'
+ apis = extension.get('supported').split('|')
+ if 'glx' in apis:
+ human_name = 'GLX extension \\"{0}\\"'.format(extname)
+ condition = 'epoxy_has_glx_extension("{0}")'.format(extname)
+ loader = 'epoxy_get_proc_address("{0}")'
+ self.process_require_statements(extension, condition, loader, human_name)
+ if 'gl' in apis:
+ human_name = 'GL extension \\"{0}\\"'.format(extname)
+ condition = 'epoxy_has_gl_extension("{0}")'.format(extname)
+ loader = 'epoxy_get_proc_address("{0}")'
+ self.process_require_statements(extension, condition, loader, human_name)
+
+ def fixup_bootstrap_function(self, name):
+ # We handle glGetString() and glGetIntegerv() specially, because we
+ # need to use them in the process of deciding on loaders for
+ # resolving, and the naive code generation would result in their
+ # resolvers calling their own resolvers.
+ if name not in self.functions:
+ return
+
+ func = self.functions[name]
+ func.providers = []
+ func.add_provider('true', self.dlsym_loader.format(func.name),
+ 'always present')
+
+ def parse(self, file):
+ reg = ET.parse(file)
+ if reg.find('comment') != None:
+ self.copyright_comment = reg.find('comment').text
+ else:
+ self.copyright_comment = ''
+ self.parse_typedefs(reg)
+ self.parse_enums(reg)
+ self.parse_function_definitions(reg)
+ self.parse_function_providers(reg)
+
+ def write_copyright_comment_body(self):
+ for line in self.copyright_comment.splitlines():
+ if '-----' in line:
+ break
+ self.outln(' * ' + line)
+
+ def write_enums(self):
+ for name, value in self.enums.items():
+ self.outln('#define ' + name.ljust(self.max_enum_name_len + 3) + value + '')
+
+ def write_function_ptr_typedefs(self):
+ for func in self.functions.values():
+ self.outln('typedef {0} (*{1})({2});'.format(func.ret_type, func.ptr_type,
+ func.args_decl))
+
+ def write_header_header(self, file):
+ self.out_file = open(file, 'w')
+
+ self.outln('/* GL dispatch header.')
+ self.outln(' * This is code-generated from the GL API XML files from Khronos.')
+ self.write_copyright_comment_body()
+ self.outln(' */')
+ self.outln('')
+
+ self.outln('#pragma once')
+
+ self.outln('#include <inttypes.h>')
+ self.outln('#include <stddef.h>')
+ self.outln('')
+
+ def write_header(self, file):
+ self.write_header_header(file)
+
+ if 'gl_' not in file:
+ self.outln('#include "epoxy/gl_generated.h"')
+ else:
+ # Add some ridiculous inttypes.h redefinitions that are from
+ # khrplatform.h and not included in the XML.
+ self.outln('typedef int8_t khronos_int8_t;')
+ self.outln('typedef int16_t khronos_int16_t;')
+ self.outln('typedef int32_t khronos_int32_t;')
+ self.outln('typedef int64_t khronos_int64_t;')
+ self.outln('typedef uint8_t khronos_uint8_t;')
+ self.outln('typedef uint16_t khronos_uint16_t;')
+ self.outln('typedef uint32_t khronos_uint32_t;')
+ self.outln('typedef uint64_t khronos_uint64_t;')
+ self.outln('typedef float khronos_float_t;')
+ self.outln('typedef intptr_t khronos_intptr_t;')
+ self.outln('typedef ptrdiff_t khronos_ssize_t;')
+
+ if 'glx_' in file:
+ self.outln('#include <X11/Xlib.h>')
+ self.outln('#include <X11/Xutil.h>')
+
+ self.out(self.typedefs)
+ self.outln('')
+ self.write_enums()
+ self.outln('')
+ self.write_function_ptr_typedefs()
+
+ for func in self.functions.values():
+ self.outln('{0} epoxy_{1}({2});'.format(func.ret_type, func.name,
+ func.args_decl))
+ self.outln('')
+
+ def write_proto_define_header(self, file, style):
+ self.write_header_header(file)
+
+ for func in self.functions.values():
+ self.outln('#define {0} epoxy_{1}{0}'.format(func.name, style))
+
+ def write_function_ptr_resolver(self, func):
+ self.outln('static {0}'.format(func.ptr_type))
+ self.outln('epoxy_{0}_resolver(void)'.format(func.name))
+ self.outln('{')
+ if 'glX' in func.name:
+ self.outln(' epoxy_glx_autoinit();')
+ else:
+ self.outln(' epoxy_platform_autoinit();')
+ self.outln('')
+
+ providers = []
+ # Make a local list of all the providers for this alias group
+ for provider in func.providers:
+ providers.append(provider)
+ for alias_func in func.alias_exts:
+ for provider in alias_func.providers:
+ providers.append(provider)
+
+ # Check if there's any alias of this that's built into our
+ # ABI, and just use that one if available. This is important
+ # for avoiding loops of
+ # glXGetProcAddress(glXGetProcAddress()), or
+ # glGetIntegerv(glGetIntegerv()).
+ global_loader = None
+ for condition, loader, human_name in providers:
+ if condition == 'true':
+ global_loader = loader
+
+ if global_loader:
+ self.outln(' return {0};'.format(loader))
+ else:
+ for condition, loader, human_name in providers:
+ self.outln(' if ({0})'.format(condition))
+ self.outln(' return {0};'.format(loader))
+ self.outln('')
+
+ # If the function isn't provided by any known extension, print
+ # something useful for the poor application developer before
+ # aborting. (In non-epoxy GL usage, the app developer would
+ # call into some blank stub function and segfault).
+ self.outln(' printf("No provider of \\"{0}()\\" found. Requires one of:\\n");'.format(func.name))
+ if len(func.providers) == 0:
+ self.outln(' printf(" unknown\\n");')
+ else:
+ for provider in func.providers:
+ self.outln(' printf(" {0}\\n");'.format(provider[2]))
+
+ self.outln(' abort();')
+
+ self.outln('}')
+ self.outln('')
+
+ def write_dispatch_table_stub(self, func):
+ dispatch_table_entry = 'dispatch_table->p{0}'.format(func.name)
+
+ # Use the same resolver for all the aliases of a particular
+ # function.
+ alias_func = func
+ if func.alias_func:
+ alias_func = func
+
+ self.outln('PUBLIC {0}'.format(func.ret_type))
+ self.outln('epoxy_{0}({1})'.format(func.name, func.args_decl))
+ self.outln('{')
+ self.outln(' if (!{0})'.format(dispatch_table_entry))
+ self.outln(' {0} = epoxy_{1}_resolver();'.format(dispatch_table_entry,
+ alias_func.name))
+ self.outln('')
+ if func.ret_type == 'void':
+ self.outln(' {0}({1});'.format(dispatch_table_entry, func.args_list))
+ else:
+ self.outln(' return {0}({1});'.format(dispatch_table_entry, func.args_list))
+ self.outln('}')
+ self.outln('')
+
+ def write_source(self, file):
+ self.out_file = open(file, 'w')
+
+ self.outln('/* GL dispatch code.')
+ self.outln(' * This is code-generated from the GL API XML files from Khronos.')
+ self.write_copyright_comment_body()
+ self.outln(' */')
+ self.outln('')
+ self.outln('#include <stdlib.h>')
+ self.outln('#include <stdio.h>')
+ self.outln('')
+ self.outln('#include "dispatch_common.h"')
+ if 'glx_' in file:
+ self.outln('#include "epoxy/glx_generated.h"')
+ else:
+ self.outln('#include "epoxy/gl_generated.h"')
+ self.outln('')
+
+ self.outln('struct dispatch_table {')
+ for func in self.functions.values():
+ self.outln(' {0} p{1};'.format(func.ptr_type, func.name))
+ self.outln('};')
+ self.outln('')
+
+ self.outln('/* XXX: Make this thread-local and swapped on makecurrent. */')
+ self.outln('static struct dispatch_table local_dispatch_table;')
+ self.outln('static struct dispatch_table *dispatch_table = &local_dispatch_table;')
+ self.outln('')
+
+ for func in self.functions.values():
+ if not func.alias_func:
+ self.write_function_ptr_resolver(func)
+
+ self.write_dispatch_table_stub(func)
+
+argparser = argparse.ArgumentParser(description='Generate GL dispatch wrappers.')
+argparser.add_argument('files', metavar='file.xml', nargs='+', help='GL API XML files to be parsed')
+argparser.add_argument('--dir', metavar='dir', required=True, help='Destination directory')
+args = argparser.parse_args()
+
+srcdir = args.dir + '/src/'
+incdir = args.dir + '/include/epoxy/'
+
+for file in args.files:
+ name = os.path.basename(file).split('.xml')[0]
+ generator = Generator()
+ generator.parse(file)
+ generator.drop_weird_glx_functions()
+ generator.fixup_bootstrap_function('glGetString')
+ generator.fixup_bootstrap_function('glGetIntegerv')
+
+ # While this is technically exposed as a GLX extension, it's
+ # required to be present as a public symbol by the Linux OpenGL
+ # ABI.
+ generator.fixup_bootstrap_function('glXGetProcAddressARB')
+
+ generator.write_header(incdir + name + '_generated.h')
+ generator.write_proto_define_header(incdir + name + '_generated_vtable_defines.h', '')
+ generator.write_source(srcdir + name + '_generated_dispatch.c')