summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChia-I Wu <olv@lunarg.com>2011-12-22 16:20:04 +0800
committerChia-I Wu <olv@lunarg.com>2011-12-28 15:46:33 +0800
commitf554bc27ec50fc2d6e790db15eb5235ae70a9d2d (patch)
treeea3f1aae43098fb66aebf7be62e253d1bd4a3c71
parent6dd1dcc91d0ed291a5a8a37f9d3e90755d0b90e3 (diff)
egl/loader: add libEGL_loadernew-egl
-rw-r--r--src/egl/loader/Makefile55
-rw-r--r--src/egl/loader/loader.c244
-rw-r--r--src/egl/loader/loader.h36
-rw-r--r--src/egl/main/eglapi.py160
4 files changed, 495 insertions, 0 deletions
diff --git a/src/egl/loader/Makefile b/src/egl/loader/Makefile
new file mode 100644
index 0000000000..f9c56560d6
--- /dev/null
+++ b/src/egl/loader/Makefile
@@ -0,0 +1,55 @@
+# src/egl/loader/Makefile
+
+TOP = ../../..
+include $(TOP)/configs/current
+
+EGL_MAJOR := 1
+EGL_MINOR := 0
+
+INCLUDE_DIRS := \
+ -I$(TOP)/include \
+ -I$(TOP)/src/egl/core
+
+LOCAL_CFLAGS := \
+ $(INCLUDE_DIRS) \
+ -D_EGL_OS_UNIX
+
+SOURCES := \
+ egl.c \
+ loader.c
+
+OBJECTS := $(SOURCES:.c=.o)
+
+.c.o:
+ $(CC) -c $(LOCAL_CFLAGS) $(CFLAGS) $< -o $@
+
+default: depend library
+
+# EGL Library
+library: $(TOP)/$(LIB_DIR)/$(EGL_LIB_NAME)
+
+$(TOP)/$(LIB_DIR)/$(EGL_LIB_NAME): $(OBJECTS)
+ $(MKLIB) -o $(EGL_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
+ -major $(EGL_MAJOR) -minor $(EGL_MINOR) \
+ -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \
+ -L$(TOP)/$(LIB_DIR) $(EGL_LIB_DEPS) \
+ $(OBJECTS)
+
+egl.c: $(TOP)/src/egl/main/egl.py
+ $(PYTHON2) $(PYTHON_FLAGS) $< loader > $@
+
+install: library
+
+clean:
+ -rm -f *.o
+ -rm -f depend depend.bak
+
+depend: $(SOURCES)
+ @ echo "running $(MKDEP)"
+ @ rm -f depend
+ @ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
+ $(SOURCES) > /dev/null 2>/dev/null
+
+-include depend
+# DO NOT DELETE
diff --git a/src/egl/loader/loader.c b/src/egl/loader/loader.c
new file mode 100644
index 0000000000..864746ffd8
--- /dev/null
+++ b/src/egl/loader/loader.c
@@ -0,0 +1,244 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.12
+ *
+ * Copyright (C) 2012 LunarG, Inc.
+ *
+ * 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 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 <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+#include "loader.h"
+
+#if defined(_EGL_OS_WINDOWS)
+
+typedef HMODULE lib_handle;
+
+static HMODULE
+open_library(const char *filename)
+{
+ return LoadLibrary(filename);
+}
+
+static __eglMustCastToProperFunctionPointerType
+lookup_library(HMODULE lib, const char *sym)
+{
+ return (__eglMustCastToProperFunctionPointerType)
+ GetProcAddress(lib, sym);
+}
+
+static void
+close_library(HMODULE lib)
+{
+ FreeLibrary(lib);
+}
+
+static const char *
+library_reason(void)
+{
+ return "unknown error";
+}
+
+static const char *
+library_suffix(void)
+{
+ return ".dll";
+}
+
+#elif defined(_EGL_OS_UNIX)
+
+#include <dlfcn.h>
+
+typedef void *lib_handle;
+
+static void *
+open_library(const char *filename)
+{
+ return dlopen(filename, RTLD_LAZY);
+}
+
+static __eglMustCastToProperFunctionPointerType
+lookup_library(void *lib, const char *sym)
+{
+ return (__eglMustCastToProperFunctionPointerType)
+ dlsym(lib, sym);
+}
+
+static void
+close_library(void *lib)
+{
+ dlclose(lib);
+}
+
+static const char *
+library_reason(void)
+{
+ return dlerror();
+}
+
+static const char *
+library_suffix(void)
+{
+ return ".so";
+}
+
+#endif /* _EGL_OS_UNIX */
+
+static lib_handle loader_impl;
+
+void
+loader_log(const char *format, ...)
+{
+ static int loader_debug = -1;
+ va_list args;
+
+ if (loader_debug < 0) {
+ const char *env = getenv("EGL_DEBUG");
+ loader_debug = (env) ? !!atoi(env) : 0;
+ }
+ if (!loader_debug)
+ return;
+
+ printf("libEGL_loader: ");
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ printf("\n");
+}
+
+static lib_handle
+loader_load_library(const char *path, const char * const *procs,
+ __eglMustCastToProperFunctionPointerType *entries)
+{
+ lib_handle impl;
+ int i;
+
+ impl = open_library(path);
+ if (!impl) {
+ loader_log("failed to load %s: %s", path, library_reason());
+ return NULL;
+ }
+
+ for (i = 0; procs[i]; i++) {
+ __eglMustCastToProperFunctionPointerType ent;
+
+ ent = lookup_library(impl, procs[i]);
+
+ if (!ent) {
+ loader_log("failed to load %s: %s missing", path, procs[i]);
+ close_library(impl);
+ return NULL;
+ }
+
+ entries[i] = ent;
+ }
+
+ return impl;
+}
+
+static lib_handle
+loader_load_impl(const char *name, const char * const *procs,
+ __eglMustCastToProperFunctionPointerType *entries)
+{
+ const char *suffix = library_suffix();
+ EGLBoolean is_file = EGL_FALSE;
+ char path[PATH_MAX];
+
+ if (suffix) {
+ size_t len = strlen(name);
+ size_t slen = strlen(suffix);
+
+ /* assume it is a filename when the suffix matches */
+ is_file = (len > slen && !strcmp(name + len - slen, suffix));
+ }
+ else {
+ suffix = "";
+ }
+
+ /* make it a filename */
+ if (!is_file) {
+ int ret;
+
+ ret = snprintf(path, sizeof(path), "libEGL_%s%s.1", name, suffix);
+ if (ret >= sizeof(path))
+ return NULL;
+
+ name = path;
+ }
+
+ return loader_load_library(name, procs, entries);
+}
+
+static lib_handle
+loader_try_impls(EGLNativeDisplayType display_id, const char **candidates,
+ const char * const *procs,
+ __eglMustCastToProperFunctionPointerType *entries)
+{
+ lib_handle impl = NULL;
+ const char **p;
+
+ for (p = candidates; *p; p++) {
+ impl = loader_load_impl(*p, procs, entries);
+ if (impl) {
+ loader_log("use %s", *p);
+ break;
+ }
+ }
+
+ return impl;
+}
+
+EGLBoolean loader_load_for_display(EGLNativeDisplayType display_id,
+ const char * const *procs, __eglMustCastToProperFunctionPointerType *entries)
+{
+ const char *candidates[8];
+ int count = 0;
+
+ if (loader_impl) {
+ close_library(loader_impl);
+ loader_impl = NULL;
+ }
+
+ candidates[count] = getenv("EGL_DRIVER");
+ if (candidates[count]) {
+ loader_log("EGL_DRIVER = %s", candidates[count]);
+
+ /* skip "egl_" prefix */
+ if (!strncmp(candidates[count], "egl_", 4))
+ candidates[count] += 4;
+ count++;
+ }
+ else {
+ candidates[count++] = "dri2";
+ candidates[count++] = "gallium";
+ candidates[count++] = "glx";
+ }
+
+ assert(count < sizeof(candidates));
+ candidates[count] = NULL;
+
+ loader_impl = loader_try_impls(display_id, candidates, procs, entries);
+
+ return (loader_impl != NULL);
+}
diff --git a/src/egl/loader/loader.h b/src/egl/loader/loader.h
new file mode 100644
index 0000000000..9c9556ecc1
--- /dev/null
+++ b/src/egl/loader/loader.h
@@ -0,0 +1,36 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.12
+ *
+ * Copyright (C) 2012 LunarG, Inc.
+ *
+ * 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 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.
+ */
+
+#ifndef _LOADER_H
+#define _LOADER_H
+
+#include <EGL/egl.h>
+
+void loader_log(const char *format, ...);
+
+EGLBoolean loader_load_for_display(EGLNativeDisplayType display_id,
+ const char * const * procs, __eglMustCastToProperFunctionPointerType *entries);
+
+#endif /* _LOADER_H */
diff --git a/src/egl/main/eglapi.py b/src/egl/main/eglapi.py
index 7af5673657..95ab352662 100644
--- a/src/egl/main/eglapi.py
+++ b/src/egl/main/eglapi.py
@@ -522,6 +522,165 @@ class EGLDriverTableCodeGen(EGLCodeGen):
print
print '#endif /* EGLAPI_INCLUDED */'
+class EGLLoaderCodeGen(EGLCodeGen):
+ """eglloader.c generator."""
+
+ def __init__(self):
+ api = egl_1_4
+
+ self.api_functions = api
+
+ loader_functions = []
+ for func in api:
+ loader_name = '_eglLoader' + func.name[3:]
+ loader_func = Function(func.ret, loader_name, func.args)
+ loader_functions.append(loader_func)
+
+ self.loader_functions = loader_functions
+
+ def gen_header(self):
+ print '/* DO NOT EDIT - This file is automatically generated. */'
+ print
+ print '#include <EGL/egl.h>'
+ print '#include "eglmutex.h"'
+ print '#include "loader.h"'
+
+ def gen_static_vars(self):
+ # declare loader's version of EGL
+ print
+ for func in self.loader_functions:
+ print 'static %s;' % func.c_proto(True)
+
+ # generate dispatch table struct
+ print
+ print 'struct _eglLoaderDispatchTable {'
+ for func in self.api_functions:
+ print ' %s (EGLAPIENTRYP %s)(%s);' \
+ % (func.ret, func.name, func.join_args())
+ print '};'
+
+ initializer = []
+ for func in self.loader_functions:
+ initializer.append(' ' + func.name)
+
+ # generate dispatch table
+ print
+ print 'static struct _eglLoaderDispatchTable _eglLoaderDispatch[2] = {'
+ print ' {'
+ print ',\n'.join(initializer)
+ print ' },'
+ print ' { NULL }'
+ print '};'
+ print
+ print '/* 0: use loader\'s, 1: use implementation\'s */'
+ print 'static int _eglLoaderDispatchIndex = 0;'
+ print
+ print 'static const char * const _eglLoaderNames[] = {'
+ for func in self.api_functions:
+ print ' "%s",' % func.name
+ print ' NULL'
+ print '};'
+
+ # generate loader error state
+ #
+ # These are really minor, but
+ #
+ # - loader_error should be thread-local
+ # - loader_error should be propogated into the implementation somehow
+ # when the dispatch table is initialized
+ print
+ print 'static EGLint _eglLoaderError = EGL_SUCCESS;'
+
+ def gen_helpers(self):
+ # gen error setting function
+ print
+ print 'static void _eglLoaderSetError(EGLint err)'
+ print '{'
+ print ' _eglLoaderError = err;'
+ print '}'
+
+ # generate dispatch table init function
+ print
+ print '/* initialize and switch dispatch table */'
+ print 'static EGLBoolean'
+ print '_eglLoaderInitDispatch(EGLNativeDisplayType display_id)'
+ print '{'
+ print ' static _EGLMutex mutex = _EGL_MUTEX_INITIALIZER;'
+ print ' static EGLBoolean initialized = EGL_FALSE;'
+ print ' EGLBoolean update = EGL_FALSE;'
+ print
+ print ' _eglLockMutex(&mutex);'
+ print ' if (!initialized) {'
+ print ' update = loader_load_for_display(display_id, _eglLoaderNames,'
+ print ' (__eglMustCastToProperFunctionPointerType *) &_eglLoaderDispatch[1]);'
+ print ' initialized = EGL_TRUE;'
+ print ' }'
+ print ' _eglUnlockMutex(&mutex);'
+ print
+ print ' if (update)'
+ print ' _eglLoaderDispatchIndex = 1;'
+ print
+ print ' return (_eglLoaderDispatchIndex == 1);'
+ print '}'
+
+ def gen_loader(self):
+ trigger_init = (
+ 'eglBindAPI',
+ 'eglGetDisplay',
+ 'eglGetProcAddress',
+ 'eglQueryAPI',
+ )
+
+ for i in xrange(len(self.api_functions)):
+ func = self.api_functions[i]
+ loader_func = self.loader_functions[i]
+
+ print
+ print 'static %s' % loader_func.c_proto()
+ print '{'
+ if func.name in trigger_init:
+ display_id = 'EGL_DEFAULT_DISPLAY'
+ if func.args and func.args[0][0] == 'EGLNativeDisplayType':
+ display_id = func.args[0][1]
+
+ # initialize the dispatch table and dispatch
+ print ' if (!_eglLoaderInitDispatch(%s))' % display_id
+ print ' return %s;' % func.return_failure()
+ print ' return _eglLoaderDispatch[1].%s;' % func.c_call()
+ elif func.args and func.args[0][0] == 'EGLDisplay':
+ # record EGL_BAD_DISPLAY and return failure
+ print ' _eglLoaderSetError(EGL_BAD_DISPLAY);'
+ print ' return %s;' % func.return_failure()
+ else:
+ # record EGL_SUCCESS and return success
+ if func.name == 'eglGetError':
+ print ' EGLint err = _eglLoaderError;'
+ ret = 'err'
+ elif func.ret == 'EGLBoolean':
+ ret = 'EGL_TRUE'
+ else:
+ # the value of failure is also the value of success
+ ret = func.return_failure()
+
+ print ' _eglLoaderSetError(EGL_SUCCESS);'
+ print ' return %s;' % ret
+ print '}'
+
+ def gen_api(self):
+ for func in self.api_functions:
+ print
+ print func.c_proto()
+ print '{'
+ print ' return _eglLoaderDispatch[_eglLoaderDispatchIndex].%s;' \
+ % func.c_call()
+ print '}'
+
+ def gen_body(self):
+ self.gen_static_vars()
+ self.gen_helpers()
+ self.gen_loader()
+ self.gen_api()
+
if __name__ == '__main__':
import sys
@@ -529,6 +688,7 @@ if __name__ == '__main__':
'api': EGLAPICodeGen,
'apidispatch': EGLAPIDispatchCodeGen,
'drivertable': EGLDriverTableCodeGen,
+ 'loader': EGLLoaderCodeGen,
}
if len(sys.argv) != 2 or sys.argv[1] not in codegens: