Add the generator and build infrastructure.

Not actually working yet, but it's a snapshot to start from.
macos/v1.5.9
Eric Anholt 11 years ago
parent db667aa8b8
commit a909eb4a22
  1. 90
      .gitignore
  2. 36
      Makefile.am
  3. 61
      README.md
  4. 14
      autogen.sh
  5. 75
      configure.ac
  6. 10
      epoxy.pc.in
  7. 52
      include/epoxy/gl.h
  8. 38
      include/epoxy/gl_common.h
  9. 51
      include/epoxy/glx.h
  10. 38
      include/epoxy/glx_common.h
  11. 84
      src/Makefile.am
  12. 217
      src/dispatch_common.c
  13. 55
      src/dispatch_common.h
  14. 456
      src/gen_dispatch.py

90
.gitignore vendored

@ -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

@ -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 \
$()

@ -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?

@ -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

@ -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"

@ -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

@ -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 */

@ -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 */

@ -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 */

@ -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 */

@ -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

@ -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();
}

@ -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);

@ -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')
Loading…
Cancel
Save