From 0270c80008e3c6b9f2f5dfba03631f72c7920796 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 2 Dec 2013 16:25:02 -0800 Subject: [PATCH] Add support for EGL. This totally replaces the getprocaddress and dlsym code, which was basically just stubs up until now. The is_glx/is_egl() is also dropped -- they weren't doing anything, and the only false answer they could give is if the dlopen were to fail. --- .gitignore | 4 + include/epoxy/egl.h | 63 ++++++++++ src/Makefile.am | 24 ++++ src/dispatch_common.c | 185 ++++++++++++++++++++++++----- src/dispatch_common.h | 27 ++--- src/gen_dispatch.py | 68 ++++++----- test/Makefile.am | 14 ++- test/egl_common.c | 50 ++++++++ test/egl_common.h | 25 ++++ test/egl_has_extension_nocontext.c | 70 +++++++++++ test/headerguards.c | 3 + 11 files changed, 452 insertions(+), 81 deletions(-) create mode 100644 include/epoxy/egl.h create mode 100644 test/egl_common.c create mode 100644 test/egl_common.h create mode 100644 test/egl_has_extension_nocontext.c diff --git a/.gitignore b/.gitignore index 91370fa..ebc2d87 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,7 @@ gl_generated_vtable_defines.h glx_generated_dispatch.c glx_generated.h glx_generated_vtable_defines.h + +egl_generated_dispatch.c +egl_generated.h +egl_generated_vtable_defines.h diff --git a/include/epoxy/egl.h b/include/epoxy/egl.h new file mode 100644 index 0000000..e30f515 --- /dev/null +++ b/include/epoxy/egl.h @@ -0,0 +1,63 @@ +/* + * 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 egl.h + * + * Provides an implementation of a EGL 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_EGL_H +#define __EPOXY_EGL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if defined(__egl_h_) || defined(__eglext_h_) +#error epoxy/egl.h must be included before (or in place of) GL/egl.h +#else +#define __egl_h_ +#define __eglext_h_ +#endif + +#pragma once + +#include "epoxy/egl_generated.h" +#include "epoxy/egl_generated_vtable_defines.h" + +bool epoxy_has_egl_extension(EGLDisplay *dpy, const char *extension); +int epoxy_egl_version(EGLDisplay *dpy); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __EPOXY_EGL_H */ diff --git a/src/Makefile.am b/src/Makefile.am index 720498a..897fa16 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,6 +31,7 @@ lib_LTLIBRARIES = libepoxy.la epoxyinclude_DATA = \ $(GL_INCLUDES) \ $(GLX_INCLUDES) \ + $(EGL_INCLUDES) \ $() GL_INCLUDES = \ @@ -43,6 +44,11 @@ GLX_INCLUDES = \ $(GENERATED_GLX_INCLUDES) \ $() +EGL_INCLUDES = \ + ../include/epoxy/egl.h \ + $(GENERATED_EGL_INCLUDES) \ + $() + GENERATED_GL_INCLUDES = \ $(builddir)/../include/epoxy/gl_generated.h \ $(builddir)/../include/epoxy/gl_generated_vtable_defines.h \ @@ -53,6 +59,11 @@ GENERATED_GLX_INCLUDES = \ $(builddir)/../include/epoxy/glx_generated_vtable_defines.h \ $() +GENERATED_EGL_INCLUDES = \ + $(tuilddir)/../include/epoxy/egl_generated.h \ + $(builddir)/../include/epoxy/egl_generated_vtable_defines.h \ + $() + GENERATED_GL_SOURCE = gl_generated_dispatch.c GENERATED_GL = \ @@ -67,9 +78,17 @@ GENERATED_GLX = \ $(GENERATED_GLX_INCLUDES) \ $() +GENERATED_EGL_SOURCE = egl_generated_dispatch.c + +GENERATED_EGL = \ + $(GENERATED_EGL_SOURCE) \ + $(GENERATED_EGL_INCLUDES) \ + $() + BUILT_SOURCES = \ $(GENERATED_GL) \ $(GENERATED_GLX) \ + $(GENERATED_EGL) \ $() CLEANFILES = $(BUILT_SOURCES) @@ -82,6 +101,7 @@ libepoxy_la_SOURCES = \ # These are generated alongside the .c file. $(GENERATED_GL_INCLUDES): $(GENERATED_GL_SOURCE) $(GENERATED_GLX_INCLUDES): $(GENERATED_GLX_SOURCE) +$(GENERATED_EGL_INCLUDES): $(GENERATED_EGL_SOURCE) $(GENERATED_GL_SOURCE): $(srcdir)/gen_dispatch.py $(top_srcdir)/registry/gl.xml $(MKDIR_P) $(top_builddir)/include/epoxy @@ -90,3 +110,7 @@ $(GENERATED_GL_SOURCE): $(srcdir)/gen_dispatch.py $(top_srcdir)/registry/gl.xml $(GENERATED_GLX_SOURCE): $(srcdir)/gen_dispatch.py $(top_srcdir)/registry/glx.xml $(MKDIR_P) $(top_builddir)/include/epoxy $(AM_V_GEN)$(PYTHON) $(srcdir)/gen_dispatch.py --dir $(top_builddir) $(top_srcdir)/registry/glx.xml + +$(GENERATED_EGL_SOURCE): $(srcdir)/gen_dispatch.py $(top_srcdir)/registry/egl.xml + $(MKDIR_P) $(top_builddir)/include/epoxy + $(AM_V_GEN)$(PYTHON) $(srcdir)/gen_dispatch.py --dir $(top_builddir) $(top_srcdir)/registry/egl.xml diff --git a/src/dispatch_common.c b/src/dispatch_common.c index 31885fb..90ff92a 100644 --- a/src/dispatch_common.c +++ b/src/dispatch_common.c @@ -93,14 +93,67 @@ #include #include #include +#include +#include #include "epoxy/gl.h" #include "epoxy/glx.h" +#include "epoxy/egl.h" #include "dispatch_common.h" -/* XXX: Make this thread local */ -struct api local_api; +struct api { + /** + * Locking for making sure we don't double-dlopen(). + */ + pthread_mutex_t mutex; + + /** dlopen() return value for libGL.so.1. */ + void *glx_handle; + + /** dlopen() return value for libEGL.so.1 */ + void *egl_handle; + + /** dlopen() return value for libGLESv1_CM.so.1 */ + void *gles1_handle; + + /** dlopen() return value for libGLESv2.so.2 */ + void *gles2_handle; +}; + +static struct api api = { + .mutex = PTHREAD_MUTEX_INITIALIZER, +}; + +static void +get_dlopen_handle(void **handle, const char *lib_name, bool exit_on_fail) +{ + if (*handle) + return; + + pthread_mutex_lock(&api.mutex); + if (!*handle) { + *handle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); + if (!*handle && exit_on_fail) { + fprintf(stderr, "Couldn't open %s: %s", lib_name, dlerror()); + exit(1); + } + } + pthread_mutex_unlock(&api.mutex); +} + +static void * +do_dlsym(void **handle, const char *lib_name, const char *name, + bool exit_on_fail) +{ + void *result; + + get_dlopen_handle(handle, lib_name, exit_on_fail); -struct api *api = &local_api; + result = dlsym(*handle, name); + if (!result) + errx(1, "%s() not found in %s", name, lib_name); + + return result; +} PUBLIC bool epoxy_is_desktop_gl(void) @@ -132,12 +185,6 @@ epoxy_gl_version(void) return 10 * major + minor; } -PUBLIC bool -epoxy_is_glx(void) -{ - return true; /* XXX */ -} - /** * If we can determine the GLX version from the current context, then * return that, otherwise return a version that will just send us on @@ -183,6 +230,30 @@ epoxy_glx_version(Display *dpy, int screen) return server; } +PUBLIC int +epoxy_conservative_egl_version(void) +{ + EGLDisplay *dpy = eglGetCurrentDisplay(); + + if (!dpy) + return 14; + + return epoxy_egl_version(dpy); +} + +PUBLIC int +epoxy_egl_version(EGLDisplay *dpy) +{ + int major, minor; + const char *version_string; + int ret; + + version_string = eglQueryString(dpy, EGL_VERSION); + ret = sscanf(version_string, "%d.%d", &major, &minor); + assert(ret == 2); + return major * 10 + minor; +} + static bool epoxy_extension_in_string(const char *extension_list, const char *ext) { @@ -204,13 +275,22 @@ epoxy_has_gl_extension(const char *ext) ext); } -#if 0 +bool +epoxy_conservative_has_egl_extension(const char *ext) +{ + EGLDisplay *dpy = eglGetCurrentDisplay(); + + if (!dpy) + return true; + + return epoxy_has_egl_extension(dpy, ext); +} + PUBLIC bool -epoxy_has_egl_extension(const char *ext) +epoxy_has_egl_extension(EGLDisplay *dpy, const char *ext) { - return epoxy_extension_in_string(eglQueryString(EGL_EXTENSIONS), ext); + return epoxy_extension_in_string(eglQueryString(dpy, EGL_EXTENSIONS), ext); } -#endif /** * If we can determine the GLX extension support from the current @@ -234,7 +314,7 @@ epoxy_conservative_has_glx_extension(const char *ext) PUBLIC bool epoxy_has_glx_extension(Display *dpy, int screen, const char *ext) -{ + { /* 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 @@ -245,37 +325,78 @@ epoxy_has_glx_extension(Display *dpy, int screen, const char *ext) } void * -epoxy_dlsym(const char *name) +epoxy_egl_dlsym(const char *name) { - assert(api->gl_handle); - return dlsym(api->gl_handle, name); + return do_dlsym(&api.egl_handle, "libEGL.so.1", name, true); } void * -epoxy_get_proc_address(const char *name) +epoxy_glx_dlsym(const char *name) { - return glXGetProcAddress((const GLubyte *)name); + return do_dlsym(&api.glx_handle, "libGL.so.1", name, true); } -void -epoxy_glx_autoinit(void) +void * +epoxy_gl_dlsym(const char *name) { - if (api->gl_handle) - return; + /* There's no library for desktop GL support independent of GLX. */ + return epoxy_glx_dlsym(name); +} - 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); - } +void * +epoxy_gles1_dlsym(const char *name) +{ + return do_dlsym(&api.gles1_handle, "libGLESv1_CM.so.1", name, true); +} - api->winsys_handle = api->gl_handle; +void * +epoxy_gles2_dlsym(const char *name) +{ + return do_dlsym(&api.gles1_handle, "libGLESv2.so.2", name, true); } -void -epoxy_platform_autoinit(void) +void * +epoxy_get_proc_address(const char *name) { - epoxy_glx_autoinit(); + if (api.egl_handle) { + return eglGetProcAddress(name); + } else if (api.glx_handle) { + return glXGetProcAddressARB((const GLubyte *)name); + } else { + /* If the application hasn't explicitly called some of our GLX + * or EGL code but has presumably set up a context on its own, + * then we need to figure out how to getprocaddress anyway. + * + * If there's a public GetProcAddress loaded in the + * application's namespace, then use that. + */ + PFNGLXGETPROCADDRESSARBPROC glx_gpa; + PFNEGLGETPROCADDRESSPROC egl_gpa; + + egl_gpa = dlsym(NULL, "eglGetProcAddress"); + if (egl_gpa) + return egl_gpa(name); + + glx_gpa = dlsym(NULL, "glXGetProcAddressARB"); + if (glx_gpa) + return glx_gpa((const GLubyte *)name); + + /* OK, couldn't find anything in the app's address space. + * Presumably they dlopened with RTLD_LOCAL, which hides it + * from us. Just go dlopen()ing likely libraries and try them. + */ + egl_gpa = do_dlsym(&api.egl_handle, "libEGL.so.1", "eglGetProcAddress", + false); + if (egl_gpa) + return egl_gpa(name); + + return do_dlsym(&api.glx_handle, "libGL.so.1", "glXGetProcAddressARB", + false); + if (glx_gpa) + return glx_gpa((const GLubyte *)name); + + errx(1, "Couldn't find GLX or EGL libraries.\n"); + } } void diff --git a/src/dispatch_common.h b/src/dispatch_common.h index 701c59c..34163ec 100644 --- a/src/dispatch_common.h +++ b/src/dispatch_common.h @@ -23,6 +23,7 @@ #include #include "epoxy/gl.h" +#include "epoxy/egl.h" #include "epoxy/glx.h" #ifndef PUBLIC @@ -33,27 +34,17 @@ # 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_glx(void); - +void *epoxy_egl_dlsym(const char *name); +void *epoxy_glx_dlsym(const char *name); +void *epoxy_gl_dlsym(const char *name); +void *epoxy_gles1_dlsym(const char *name); +void *epoxy_gles2_dlsym(const char *name); void *epoxy_get_proc_address(const char *name); + int epoxy_conservative_glx_version(void); bool epoxy_conservative_has_glx_extension(const char *name); -void *epoxy_dlsym(const char *name); -void epoxy_glx_autoinit(void); -void epoxy_platform_autoinit(void); +int epoxy_conservative_egl_version(void); +bool epoxy_conservative_has_egl_extension(const char *name); void epoxy_print_failure_reasons(const char *name, const char **provider_names, const int *providers); diff --git a/src/gen_dispatch.py b/src/gen_dispatch.py index 4310246..168112b 100755 --- a/src/gen_dispatch.py +++ b/src/gen_dispatch.py @@ -116,9 +116,6 @@ class Generator(object): self.typedefs = '' self.out_file = None - self.dlsym_loader = 'epoxy_dlsym({0})' - self.gpa_loader = 'epoxy_get_proc_address({0})' - # Dictionary mapping human-readable names of providers to a C # enum token that will be used to reference those names, to # reduce generated binary size. @@ -266,36 +263,41 @@ class Generator(object): # else is supposed to not be present, so you have to # glXGetProcAddress() it. if version <= 12: - loader = self.dlsym_loader + loader = 'epoxy_gl_dlsym({0})' else: - loader = self.gpa_loader + loader = 'epoxy_get_proc_address({0})' 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 + loader = 'epoxy_gles2_dlsym({0})' else: - loader = self.gpa_loader + loader = 'epoxy_get_proc_address({0})' 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 + loader = 'epoxy_gles1_dlsym({0})' elif api == 'glx': human_name = 'GLX {0}'.format(version) - condition = 'epoxy_is_glx()' - # We could just always use GPA, but dlsym() is a more + # We could just always use GPA for loading everything + # but glXGetProcAddress(), but dlsym() is a more # efficient lookup. if version > 13: - condition = condition + ' && epoxy_conservative_glx_version() >= {0}'.format(version) - loader = self.gpa_loader + condition = 'epoxy_conservative_glx_version() >= {0}'.format(version) + loader = 'glXGetProcAddress((const GLubyte *){0})' + else: + condition = 'true' + loader = 'epoxy_glx_dlsym({0})' + elif api == 'egl': + human_name = 'EGL {0}'.format(version) + if version > 10: + condition = 'epoxy_conservative_egl_version() >= {0}'.format(version) + loader = 'eglGetProcAddress({0})' else: - loader = self.dlsym_loader + condition = 'true' + loader = 'epoxy_egl_dlsym({0})' else: sys.exit('unknown API: "{0}"'.format(api)) @@ -309,15 +311,20 @@ class Generator(object): if 'glx' in apis: human_name = 'GLX extension \\"{0}\\"'.format(extname) condition = 'epoxy_conservative_has_glx_extension("{0}")'.format(extname) - loader = self.gpa_loader + loader = 'glXGetProcAddress((const GLubyte *){0})' + self.process_require_statements(extension, condition, loader, human_name) + if 'egl' in apis: + human_name = 'EGL extension \\"{0}\\"'.format(extname) + condition = 'epoxy_conservative_has_egl_extension("{0}")'.format(extname) + loader = 'eglGetProcAddress({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 = self.gpa_loader + loader = 'epoxy_get_proc_address({0})' self.process_require_statements(extension, condition, loader, human_name) - def fixup_bootstrap_function(self, name): + def fixup_bootstrap_function(self, name, loader): # 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 @@ -327,7 +334,7 @@ class Generator(object): func = self.functions[name] func.providers = {} - func.add_provider('true', self.dlsym_loader, 'always present') + func.add_provider('true', loader, 'always present') def parse(self, file): reg = ET.parse(file) @@ -375,6 +382,8 @@ class Generator(object): if self.target != "gl": self.outln('#include "epoxy/gl_generated.h"') + if self.target == "egl": + self.outln('#include "EGL/eglplatform.h"') else: # Add some ridiculous inttypes.h redefinitions that are from # khrplatform.h and not included in the XML. @@ -389,6 +398,8 @@ class Generator(object): self.outln('typedef float khronos_float_t;') self.outln('typedef intptr_t khronos_intptr_t;') self.outln('typedef ptrdiff_t khronos_ssize_t;') + self.outln('typedef uint64_t khronos_utime_nanoseconds_t;') + self.outln('typedef int64_t khronos_stime_nanoseconds_t;') if self.target == "glx": self.outln('#include ') @@ -435,12 +446,6 @@ class Generator(object): self.outln(' "{0}",'.format(provider.name)) self.outln(' };') - if 'glX' in func.name: - self.outln(' epoxy_glx_autoinit();') - else: - self.outln(' epoxy_platform_autoinit();') - self.outln('') - self.outln(' return {0}_provider_resolver("{1}",'.format(self.target, func.name)) self.outln(' providers, entrypoints);') @@ -583,13 +588,16 @@ for file in args.files: generator.drop_weird_glx_functions() generator.sort_functions() generator.resolve_aliases() - generator.fixup_bootstrap_function('glGetString') - generator.fixup_bootstrap_function('glGetIntegerv') + generator.fixup_bootstrap_function('glGetString', + 'epoxy_get_proc_address({0})') + generator.fixup_bootstrap_function('glGetIntegerv', + 'epoxy_get_proc_address({0})') # 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('glXGetProcAddress') + generator.fixup_bootstrap_function('glXGetProcAddress', + 'epoxy_glx_dlsym({0})') generator.prepare_provider_enum() diff --git a/test/Makefile.am b/test/Makefile.am index 81263b0..01fdc65 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -20,7 +20,15 @@ EPOXY = $(builddir)/../src/libepoxy.la -check_LTLIBRARIES = libglx_common.la +check_LTLIBRARIES = \ + libegl_common.la \ + libglx_common.la \ + $() + +libegl_common_la_SOURCES = \ + egl_common.c \ + egl_common.h + $() libglx_common_la_SOURCES = \ glx_common.c \ @@ -32,6 +40,7 @@ AM_CPPFLAGS = \ $(X11_CFLAGS) TESTS = \ + egl_has_extension_nocontext \ glx_public_api \ glx_glxgetprocaddress_nocontext \ glx_has_extension_nocontext \ @@ -40,6 +49,9 @@ TESTS = \ check_PROGRAMS = $(TESTS) +egl_has_extension_nocontext_LDFLAGS = $(X11_LIBS) $(EPOXY) libegl_common.la +egl_has_extension_nocontext_DEPENDENCIES = libegl_common.la + glx_public_api_LDFLAGS = $(X11_LIBS) $(EPOXY) libglx_common.la glx_public_api_DEPENDENCIES = libglx_common.la diff --git a/test/egl_common.c b/test/egl_common.c new file mode 100644 index 0000000..4cc0409 --- /dev/null +++ b/test/egl_common.c @@ -0,0 +1,50 @@ +/* + * 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 +#include + +/** + * Do whatever it takes to get us an EGL display for the system. + * + * This needs to be ported to other window systems. + */ +EGLDisplay * +get_egl_display_or_skip(void) +{ + Display *dpy = XOpenDisplay(NULL); + EGLint major, minor; + + if (!dpy) + errx(77, "couldn't open display\n"); + + EGLDisplay *edpy = eglGetDisplay(dpy); + if (!edpy) + errx(1, "Couldn't get EGL display for X11 Display.\n"); + + bool ok = eglInitialize(edpy, &major, &minor); + if (!ok) + errx(1, "eglInitialize() failed\n"); + + return edpy; +} diff --git a/test/egl_common.h b/test/egl_common.h new file mode 100644 index 0000000..1c5963b --- /dev/null +++ b/test/egl_common.h @@ -0,0 +1,25 @@ +/* + * 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. + */ + +EGLDisplay * +get_egl_display_or_skip(void); diff --git a/test/egl_has_extension_nocontext.c b/test/egl_has_extension_nocontext.c new file mode 100644 index 0000000..7f658af --- /dev/null +++ b/test/egl_has_extension_nocontext.c @@ -0,0 +1,70 @@ +/* + * 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 egl_has_extension_nocontext.c + * + * Catches a bug in early development where eglGetProcAddress() with + * no context bound would fail out in dispatch. + */ + +#include +#include +#include +#include +#include +#include "epoxy/gl.h" +#include "epoxy/egl.h" + +#include "egl_common.h" + +int +main(int argc, char **argv) +{ + bool pass = true; + + EGLDisplay *dpy = get_egl_display_or_skip(); + const char *extensions = eglQueryString(dpy, EGL_EXTENSIONS); + char *first_space; + char *an_extension; + + /* We don't have any extensions guaranteed by the ABI, so for the + * touch test we just check if the first one is reported to be there. + */ + first_space = strstr(extensions, " "); + if (first_space) { + an_extension = strndup(extensions, first_space - extensions); + } else { + an_extension = strdup(extensions); + } + + if (!epoxy_has_egl_extension(dpy, an_extension)) + errx(1, "Implementation reported absence of GLX_ARB_get_proc_address"); + + free(an_extension); + + if (epoxy_has_egl_extension(dpy, "GLX_ARB_ham_sandwich")) + errx(1, "Implementation reported presence of GLX_ARB_ham_sandwich"); + + return pass != true; +} diff --git a/test/headerguards.c b/test/headerguards.c index 17e6aef..a270b53 100644 --- a/test/headerguards.c +++ b/test/headerguards.c @@ -22,8 +22,11 @@ */ #include +#include #include +#include +#include #include #include #include