-I. \
-I$(TOP)/src/gallium/include \
-I$(TOP)/src/gallium/auxiliary \
- -I$(TOP)/src/gallium/drivers \
-I$(TOP)/src/egl/main \
-I$(TOP)/include
common_SOURCES = $(wildcard common/*.c)
common_OBJECTS = $(common_SOURCES:.c=.o)
-
x11_INCLUDES = \
-I$(TOP)/src/gallium/drivers \
-I$(TOP)/src/glx \
kms_OBJECTS = $(kms_SOURCES:.c=.o)
-fbdev_INCLUDES = -I$(TOP)/src/gallium/winsys/sw -I$(TOP)/src/gallium/drivers
+fbdev_INCLUDES = -I$(TOP)/src/gallium/winsys/sw
fbdev_SOURCES = $(wildcard fbdev/*.c)
fbdev_OBJECTS = $(fbdev_SOURCES:.c=.o)
ALL_SOURCES = $(common_SOURCES) $(x11_SOURCES) $(kms_SOURCES) $(fbdev_SOURCES)
EGL_OBJECTS = $(common_OBJECTS)
-EGL_CPPFLAGS = $(common_INCLUDES) -DST_MODULE_PREFIX=\"st_\"
+EGL_CPPFLAGS = $(common_INCLUDES)
# add backends
ifneq ($(findstring x11, $(EGL_PLATFORMS)),)
#include "egl_g3d.h"
#include "egl_g3d_api.h"
#include "egl_g3d_st.h"
+#include "egl_g3d_loader.h"
#include "native.h"
-/**
- * Initialize the state trackers.
- */
-static void
-egl_g3d_init_st(_EGLDriver *drv)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- EGLint i;
-
- /* already initialized */
- if (gdrv->api_mask)
- return;
-
- egl_g3d_init_st_apis(gdrv->stapis);
- for (i = 0; i < ST_API_COUNT; i++) {
- if (gdrv->stapis[i])
- gdrv->api_mask |= egl_g3d_st_api_bit(i);
- }
-
- if (gdrv->api_mask)
- _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask);
- else
- _eglLog(_EGL_WARNING, "No supported client API");
-}
-
/**
* Get the native platform.
*/
_EGLConfig *conf, const struct native_config *nconf,
enum pipe_format depth_stencil_format)
{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
struct egl_g3d_config *gconf = egl_g3d_config(conf);
EGLint buffer_mask, api_mask;
EGLBoolean valid;
gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ?
ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT;
- api_mask = gdrv->api_mask;;
+ api_mask = dpy->ClientAPIsMask;
/* this is required by EGL, not by OpenGL ES */
if (nconf->window_bit &&
gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT)
gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi);
}
+static struct pipe_screen *
+egl_g3d_new_drm_screen(struct native_display *ndpy, const char *name, int fd)
+{
+ _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ return gdpy->loader->create_drm_screen(name, fd);
+}
+
+static struct pipe_screen *
+egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws)
+{
+ _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data;
+ struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
+ return gdpy->loader->create_sw_screen(ws);
+}
+
static struct native_event_handler egl_g3d_native_event_handler = {
- egl_g3d_invalid_surface
+ egl_g3d_invalid_surface,
+ egl_g3d_new_drm_screen,
+ egl_g3d_new_sw_screen
};
static EGLBoolean
_eglError(EGL_BAD_ALLOC, "eglInitialize");
goto fail;
}
+ gdpy->loader = gdrv->loader;
dpy->DriverData = gdpy;
_eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay);
gdpy->native = nplat->create_display(dpy->PlatformDisplay,
- &egl_g3d_native_event_handler);
+ &egl_g3d_native_event_handler, (void *) dpy);
if (!gdpy->native) {
_eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)");
goto fail;
}
- gdpy->native->user_data = (void *) dpy;
-
- egl_g3d_init_st(&gdrv->base);
- dpy->ClientAPIsMask = gdrv->api_mask;
+ if (gdpy->loader->api_mask & (1 << ST_API_OPENGL))
+ dpy->ClientAPIsMask |= EGL_OPENGL_BIT;
+ if (gdpy->loader->api_mask & (1 << ST_API_OPENGL_ES1))
+ dpy->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
+ if (gdpy->loader->api_mask & (1 << ST_API_OPENGL_ES2))
+ dpy->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
+ if (gdpy->loader->api_mask & (1 << ST_API_OPENVG))
+ dpy->ClientAPIsMask |= EGL_OPENVG_BIT;
gdpy->smapi = egl_g3d_create_st_manager(dpy);
if (!gdpy->smapi) {
egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname)
{
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- _EGLProc proc;
- EGLint i;
+ struct st_api *stapi = NULL;
- /* in case this is called before a display is initialized */
- egl_g3d_init_st(&gdrv->base);
-
- for (i = 0; i < ST_API_COUNT; i++) {
- struct st_api *stapi = gdrv->stapis[i];
- if (stapi) {
- proc = (_EGLProc) stapi->get_proc_address(stapi, procname);
- if (proc)
- return proc;
- }
- }
+ if (procname && procname[0] == 'v' && procname[1] == 'g')
+ stapi = gdrv->loader->get_st_api(ST_API_OPENVG);
+ else if (procname && procname[0] == 'g' && procname[1] == 'l')
+ stapi = gdrv->loader->guess_gl_api();
- return (_EGLProc) NULL;
+ return (_EGLProc) ((stapi) ?
+ stapi->get_proc_address(stapi, procname) : NULL);
}
static EGLint
return score;
}
-static void
-egl_g3d_unload(_EGLDriver *drv)
-{
- struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
-
- egl_g3d_destroy_st_apis();
- egl_g3d_destroy_probe(drv, NULL);
- FREE(gdrv);
-}
-
_EGLDriver *
-_eglMain(const char *args)
+egl_g3d_create_driver(const struct egl_g3d_loader *loader)
{
struct egl_g3d_driver *gdrv;
if (!gdrv)
return NULL;
+ gdrv->loader = loader;
+
egl_g3d_init_driver_api(&gdrv->base);
gdrv->base.API.Initialize = egl_g3d_initialize;
gdrv->base.API.Terminate = egl_g3d_terminate;
gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address;
- gdrv->base.Name = "Gallium";
gdrv->base.Probe = egl_g3d_probe;
- gdrv->base.Unload = egl_g3d_unload;
/* the key is " EGL G3D" */
gdrv->probe_key = 0x0E61063D;
+ /* to be filled by the caller */
+ gdrv->base.Name = NULL;
+ gdrv->base.Unload = NULL;
+
return &gdrv->base;
}
+
+void
+egl_g3d_destroy_driver(_EGLDriver *drv)
+{
+ struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
+ FREE(gdrv);
+}
#include "native.h"
#include "egl_g3d_st.h"
+#include "egl_g3d_loader.h"
struct egl_g3d_driver {
_EGLDriver base;
- struct st_api *stapis[ST_API_COUNT];
- EGLint api_mask;
-
+ const struct egl_g3d_loader *loader;
const struct native_platform *platforms[_EGL_NUM_PLATFORMS];
EGLint probe_key;
};
struct egl_g3d_display {
struct native_display *native;
+ const struct egl_g3d_loader *loader;
struct st_manager *smapi;
struct pipe_context *pipe;
};
#include "egl_g3d_api.h"
#include "egl_g3d_image.h"
#include "egl_g3d_st.h"
+#include "egl_g3d_loader.h"
#include "native.h"
/**
egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx)
{
struct egl_g3d_driver *gdrv = egl_g3d_driver(drv);
- struct st_api *stapi;
EGLint idx = -1;
switch (ctx->ClientAPI) {
break;
}
- stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL;
- return stapi;
+ return (idx >= 0) ? gdrv->loader->get_st_api(idx) : NULL;
}
static _EGLContext *
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.9
+ *
+ * Copyright (C) 2010 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.
+ *
+ * Authors:
+ * Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef _EGL_G3D_LOADER_H_
+#define _EGL_G3D_LOADER_H_
+
+#include "pipe/p_compiler.h"
+#include "state_tracker/st_api.h"
+#include "egltypedefs.h"
+
+struct pipe_screen;
+struct sw_winsys;
+
+struct egl_g3d_loader {
+ uint api_mask;
+ struct st_api *(*get_st_api)(enum st_api_type api);
+ struct st_api *(*guess_gl_api)(void);
+
+ struct pipe_screen *(*create_drm_screen)(const char *name, int fd);
+ struct pipe_screen *(*create_sw_screen)(struct sw_winsys *ws);
+};
+
+_EGLDriver *
+egl_g3d_create_driver(const struct egl_g3d_loader *loader);
+
+void
+egl_g3d_destroy_driver(_EGLDriver *drv);
+
+#endif /* _EGL_G3D_LOADER_H_ */
return (struct egl_g3d_st_manager *) smapi;
}
-static struct egl_g3d_st_module {
- const char *filename;
- struct util_dl_library *lib;
- struct st_api *stapi;
-} egl_g3d_st_modules[ST_API_COUNT];
-
-static EGLBoolean
-egl_g3d_search_path_callback(const char *dir, size_t len, void *callback_data)
-{
- struct egl_g3d_st_module *stmod =
- (struct egl_g3d_st_module *) callback_data;
- char path[1024];
- int ret;
-
- if (!len) {
- stmod->lib = util_dl_open(stmod->filename);
- return !(stmod->lib);
- }
-
- ret = util_snprintf(path, sizeof(path),
- "%.*s/%s", len, dir, stmod->filename);
- if (ret > 0 && ret < sizeof(path))
- stmod->lib = util_dl_open(path);
-
- return !(stmod->lib);
-}
-
-static boolean
-egl_g3d_load_st_module(struct egl_g3d_st_module *stmod,
- const char *filename, const char *procname)
-{
- struct st_api *(*create_api)(void);
-
- stmod->filename = filename;
- if (stmod->filename)
- _eglSearchPathForEach(egl_g3d_search_path_callback, (void *) stmod);
- else
- stmod->lib = util_dl_open(NULL);
-
- if (stmod->lib) {
- create_api = (struct st_api *(*)(void))
- util_dl_get_proc_address(stmod->lib, procname);
- if (create_api)
- stmod->stapi = create_api();
-
- if (!stmod->stapi) {
- util_dl_close(stmod->lib);
- stmod->lib = NULL;
- }
- }
-
- if (stmod->stapi) {
- return TRUE;
- }
- else {
- stmod->filename = NULL;
- return FALSE;
- }
-}
-
-#ifdef PIPE_OS_WINDOWS
-#define ST_MODULE_SUFFIX ".dll"
-#else
-#define ST_MODULE_SUFFIX ".so"
-#endif
-
-void
-egl_g3d_init_st_apis(struct st_api *stapis[ST_API_COUNT])
-{
- const char *skip_checks[ST_API_COUNT], *symbols[ST_API_COUNT];
- const char *filenames[ST_API_COUNT][4];
- struct util_dl_library *self;
- int num_needed = 0, api;
-
- self = util_dl_open(NULL);
-
- /* collect the necessary data for loading modules */
- for (api = 0; api < ST_API_COUNT; api++) {
- int count = 0;
-
- switch (api) {
- case ST_API_OPENGL:
- skip_checks[api] = "glColor4d";
- symbols[api] = ST_CREATE_OPENGL_SYMBOL;
- filenames[api][count++] = ST_MODULE_PREFIX "GL" ST_MODULE_SUFFIX;
- break;
- case ST_API_OPENGL_ES1:
- skip_checks[api] = "glColor4x";
- symbols[api] = ST_CREATE_OPENGL_ES1_SYMBOL;
- filenames[api][count++] = ST_MODULE_PREFIX "GLESv1_CM" ST_MODULE_SUFFIX;
- filenames[api][count++] = ST_MODULE_PREFIX "GL" ST_MODULE_SUFFIX;
- break;
- case ST_API_OPENGL_ES2:
- skip_checks[api] = "glShaderBinary";
- symbols[api] = ST_CREATE_OPENGL_ES2_SYMBOL;
- filenames[api][count++] = ST_MODULE_PREFIX "GLESv2" ST_MODULE_SUFFIX;
- filenames[api][count++] = ST_MODULE_PREFIX "GL" ST_MODULE_SUFFIX;
- break;
- case ST_API_OPENVG:
- skip_checks[api] = "vgClear";
- symbols[api] = ST_CREATE_OPENVG_SYMBOL;
- filenames[api][count++]= ST_MODULE_PREFIX "OpenVG" ST_MODULE_SUFFIX;
- break;
- default:
- assert(!"Unknown API Type\n");
- skip_checks[api] = NULL;
- symbols[api] = NULL;
- break;
- }
- filenames[api][count++]= NULL;
- assert(count < Elements(filenames[api]));
-
- /* heuristicically decide if the module is needed */
- if (!self || !skip_checks[api] ||
- util_dl_get_proc_address(self, skip_checks[api])) {
- /* unset so the module is not skipped */
- skip_checks[api] = NULL;
- num_needed++;
- }
- }
- /* mark all moudles needed if we wrongly decided that none is needed */
- if (!num_needed)
- memset(skip_checks, 0, sizeof(skip_checks));
-
- if (self)
- util_dl_close(self);
-
- for (api = 0; api < ST_API_COUNT; api++) {
- struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api];
- const char **p;
-
- /* skip the module */
- if (skip_checks[api])
- continue;
-
- /* try all filenames, including NULL */
- for (p = filenames[api]; *p; p++) {
- if (egl_g3d_load_st_module(stmod, *p, symbols[api]))
- break;
- }
- if (!stmod->stapi)
- egl_g3d_load_st_module(stmod, NULL, symbols[api]);
-
- stapis[api] = stmod->stapi;
- }
-}
-
-void
-egl_g3d_destroy_st_apis(void)
-{
- int api;
-
- for (api = 0; api < ST_API_COUNT; api++) {
- struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api];
-
- if (stmod->stapi) {
- stmod->stapi->destroy(stmod->stapi);
- stmod->stapi = NULL;
- }
- if (stmod->lib) {
- util_dl_close(stmod->lib);
- stmod->lib = NULL;
- }
- stmod->filename = NULL;
- }
-}
-
static boolean
egl_g3d_st_manager_get_egl_image(struct st_manager *smapi,
struct st_context_iface *stctx,
#include "state_tracker/st_api.h"
#include "egltypedefs.h"
-void
-egl_g3d_init_st_apis(struct st_api *stapis[ST_API_COUNT]);
-
-void
-egl_g3d_destroy_st_apis(void);
-
struct st_manager *
egl_g3d_create_st_manager(_EGLDisplay *dpy);
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
+#include "state_tracker/sw_winsys.h"
#include "native_probe.h"
#include "native_modeset.h"
void (*invalid_surface)(struct native_display *ndpy,
struct native_surface *nsurf,
unsigned int seq_num);
+
+ struct pipe_screen *(*new_drm_screen)(struct native_display *ndpy,
+ const char *name, int fd);
+ struct pipe_screen *(*new_sw_screen)(struct native_display *ndpy,
+ struct sw_winsys *ws);
};
/**
enum native_probe_result (*get_probe_result)(struct native_probe *nprobe);
struct native_display *(*create_display)(void *dpy,
- struct native_event_handler *handler);
+ struct native_event_handler *handler,
+ void *user_data);
};
const struct native_platform *
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
-#include "softpipe/sp_public.h"
-#include "llvmpipe/lp_public.h"
-#include "target-helpers/wrap_screen.h"
#include "native_helper.h"
return TRUE;
}
-
-struct pipe_screen *
-native_create_sw_screen(struct sw_winsys *ws)
-{
- struct pipe_screen *screen = NULL;
-
-#if defined(GALLIUM_LLVMPIPE)
- if (!screen && !debug_get_bool_option("GALLIUM_NO_LLVM", FALSE))
- screen = llvmpipe_create_screen(ws);
-#endif
- if (!screen)
- screen = softpipe_create_screen(ws);
-
- return (screen) ? gallium_wrap_screen(screen) : NULL;
-}
resource_surface_present(struct resource_surface *rsurf,
enum native_attachment which,
void *winsys_drawable_handle);
-
-struct pipe_screen *
-native_create_sw_screen(struct sw_winsys *ws);
return FALSE;
ws = fbdev_create_sw_winsys(fbdpy->fd, fbdpy->config.color_format);
- if (ws)
- fbdpy->base.screen = native_create_sw_screen(ws);
+ if (ws) {
+ fbdpy->base.screen =
+ fbdpy->event_handler->new_sw_screen(&fbdpy->base, ws);
+ }
if (fbdpy->base.screen) {
if (!fbdpy->base.screen->is_format_supported(fbdpy->base.screen,
}
static struct native_display *
-fbdev_display_create(int fd, struct native_event_handler *event_handler)
+fbdev_display_create(int fd, struct native_event_handler *event_handler,
+ void *user_data)
{
struct fbdev_display *fbdpy;
fbdpy->fd = fd;
fbdpy->event_handler = event_handler;
+ fbdpy->base.user_data = user_data;
if (!fbdev_display_init(&fbdpy->base)) {
FREE(fbdpy);
}
static struct native_display *
-native_create_display(void *dpy, struct native_event_handler *event_handler)
+native_create_display(void *dpy, struct native_event_handler *event_handler,
+ void *user_data)
{
struct native_display *ndpy;
int fd;
if (fd < 0)
return NULL;
- ndpy = fbdev_display_create(fd, event_handler);
+ ndpy = fbdev_display_create(fd, event_handler, user_data);
if (!ndpy)
close(fd);
}
static struct native_display *
-gdi_create_display(HDC hDC, struct pipe_screen *screen,
- struct native_event_handler *event_handler)
+gdi_create_display(HDC hDC, struct native_event_handler *event_handler,
+ void *user_data)
{
struct gdi_display *gdpy;
+ struct sw_winsys *winsys;
gdpy = CALLOC_STRUCT(gdi_display);
if (!gdpy)
gdpy->hDC = hDC;
gdpy->event_handler = event_handler;
+ gdpy->base.user_data = user_data;
+
+ winsys = gdi_create_sw_winsys();
+ if (!winsys) {
+ FREE(gdpy);
+ return NULL;
+ }
- gdpy->base.screen = screen;
+ gdpy->base.screen = gdpy->event_handler->create_sw_screen(winsys);
+ if (!gdpy->base.screen) {
+ if (winsys->destroy)
+ winsys->destroy(winsys);
+ FREE(gdpy);
+ return NULL;
+ }
gdpy->base.destroy = gdi_display_destroy;
gdpy->base.get_param = gdi_display_get_param;
}
static struct native_display *
-native_create_display(void *dpy, struct native_event_handler *event_handler)
+native_create_display(void *dpy, struct native_event_handler *event_handler,
+ void *user_data)
{
- struct sw_winsys *winsys;
- struct pipe_screen *screen;
-
- winsys = gdi_create_sw_winsys();
- if (!winsys)
- return NULL;
-
- screen = native_create_sw_screen(winsys);
- if (!screen) {
- if (winsys->destroy)
- winsys->destroy(winsys);
- return NULL;
- }
-
- return gdi_create_display((HDC) dpy, screen, event_handler);
+ return gdi_create_display((HDC) dpy, event_handler, user_data);
}
static const struct native_platform gdi_platform = {
* DEALINGS IN THE SOFTWARE.
*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "util/u_debug.h"
#include "egllog.h"
#include "native_kms.h"
-#include "state_tracker/drm_driver.h"
static boolean
kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
kdpy->base.screen->destroy(kdpy->base.screen);
if (kdpy->fd >= 0)
- drmClose(kdpy->fd);
+ close(kdpy->fd);
FREE(kdpy);
}
kms_display_init_screen(struct native_display *ndpy)
{
struct kms_display *kdpy = kms_display(ndpy);
- int fd;
-
- fd = kdpy->fd;
- if (fd >= 0) {
- drmVersionPtr version = drmGetVersion(fd);
- if (!version || strcmp(version->name, driver_descriptor.driver_name)) {
- if (version) {
- _eglLog(_EGL_WARNING, "unknown driver name %s", version->name);
- drmFreeVersion(version);
- }
- else {
- _eglLog(_EGL_WARNING, "invalid fd %d", fd);
- }
-
- return FALSE;
- }
+ drmVersionPtr version;
- drmFreeVersion(version);
- }
- else {
- fd = drmOpen(driver_descriptor.driver_name, NULL);
- }
-
- if (fd < 0) {
- _eglLog(_EGL_WARNING, "failed to open DRM device");
+ version = drmGetVersion(kdpy->fd);
+ if (!version) {
+ _eglLog(_EGL_WARNING, "invalid fd %d", kdpy->fd);
return FALSE;
}
-#if 0
- if (drmSetMaster(fd)) {
- _eglLog(_EGL_WARNING, "failed to become DRM master");
- return FALSE;
- }
-#endif
+ kdpy->base.screen = kdpy->event_handler->new_drm_screen(&kdpy->base,
+ version->name, kdpy->fd);;
+ drmFreeVersion(version);
- kdpy->base.screen = driver_descriptor.create_screen(fd);
if (!kdpy->base.screen) {
_eglLog(_EGL_WARNING, "failed to create DRM screen");
- drmClose(fd);
return FALSE;
}
- kdpy->fd = fd;
-
return TRUE;
}
};
static struct native_display *
-kms_create_display(int fd, struct native_event_handler *event_handler)
+kms_create_display(int fd, struct native_event_handler *event_handler,
+ void *user_data)
{
struct kms_display *kdpy;
if (!kdpy)
return NULL;
- kdpy->event_handler = event_handler;
kdpy->fd = fd;
+ kdpy->event_handler = event_handler;
+ kdpy->base.user_data = user_data;
+
if (!kms_display_init_screen(&kdpy->base)) {
kms_display_destroy(&kdpy->base);
return NULL;
}
static struct native_display *
-native_create_display(void *dpy, struct native_event_handler *event_handler)
+native_create_display(void *dpy, struct native_event_handler *event_handler,
+ void *user_data)
{
- struct native_display *ndpy;
int fd;
- /* well, this makes fd 0 being ignored */
- fd = (dpy) ? (int) pointer_to_intptr(dpy) : -1;
- ndpy = kms_create_display(fd, event_handler);
-
- return ndpy;
-}
-
-static void
-kms_init_platform(struct native_platform *nplat)
-{
- static char kms_name[32];
-
- if (nplat->name)
- return;
-
- util_snprintf(kms_name, sizeof(kms_name), "KMS/%s", driver_descriptor.name);
+ if (dpy) {
+ fd = dup((int) pointer_to_intptr(dpy));
+ }
+ else {
+ fd = open("/dev/dri/card0", O_RDWR);
+ }
+ if (fd < 0)
+ return NULL;
- nplat->name = kms_name;
- nplat->create_probe = NULL;
- nplat->get_probe_result = NULL;
- nplat->create_display = native_create_display;
+ return kms_create_display(fd, event_handler, user_data);
}
-static struct native_platform kms_platform;
+static const struct native_platform kms_platform = {
+ "KMS", /* name */
+ NULL, /* create_probe */
+ NULL, /* get_probe_result */
+ native_create_display
+};
const struct native_platform *
native_get_kms_platform(void)
{
- kms_init_platform(&kms_platform);
return &kms_platform;
}
#include "pipe/p_compiler.h"
#include "util/u_format.h"
#include "pipe/p_state.h"
+#include "state_tracker/drm_driver.h"
#include "common/native.h"
#include "common/native_helper.h"
dri2_display_init_screen(struct native_display *ndpy)
{
struct dri2_display *dri2dpy = dri2_display(ndpy);
- const char *driver = driver_descriptor.name;
int fd;
if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr,
&dri2dpy->dri_major, &dri2dpy->dri_minor);
- if (!dri2dpy->dri_driver || !driver ||
- strcmp(dri2dpy->dri_driver, driver) != 0) {
- _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
- dri2dpy->dri_driver, driver);
- return FALSE;
- }
fd = x11_screen_enable_dri2(dri2dpy->xscr,
dri2_display_invalidate_buffers, &dri2dpy->base);
if (fd < 0)
return FALSE;
- dri2dpy->base.screen = driver_descriptor.create_screen(fd);
+ dri2dpy->base.screen =
+ dri2dpy->event_handler->new_drm_screen(&dri2dpy->base,
+ dri2dpy->dri_driver, fd);
if (!dri2dpy->base.screen) {
_eglLog(_EGL_WARNING, "failed to create DRM screen");
return FALSE;
struct native_display *
x11_create_dri2_display(Display *dpy,
- struct native_event_handler *event_handler)
+ struct native_event_handler *event_handler,
+ void *user_data)
{
struct dri2_display *dri2dpy;
return NULL;
dri2dpy->event_handler = event_handler;
+ dri2dpy->base.user_data = user_data;
dri2dpy->dpy = dpy;
if (!dri2dpy->dpy) {
* DEALINGS IN THE SOFTWARE.
*/
-#include <string.h>
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_string.h"
}
static struct native_display *
-native_create_display(void *dpy, struct native_event_handler *event_handler)
+native_create_display(void *dpy, struct native_event_handler *event_handler,
+ void *user_data)
{
struct native_display *ndpy = NULL;
boolean force_sw;
force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE);
- if (!driver_descriptor.create_screen)
- force_sw = TRUE;
-
if (!force_sw) {
- ndpy = x11_create_dri2_display((Display *) dpy, event_handler);
+ ndpy = x11_create_dri2_display((Display *) dpy,
+ event_handler, user_data);
}
if (!ndpy) {
EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING;
_eglLog(level, "use software fallback");
- ndpy = x11_create_ximage_display((Display *) dpy, event_handler);
+ ndpy = x11_create_ximage_display((Display *) dpy,
+ event_handler, user_data);
}
return ndpy;
}
-static void
-x11_init_platform(struct native_platform *nplat)
-{
- static char x11_name[32];
-
- if (nplat->name)
- return;
-
- util_snprintf(x11_name, sizeof(x11_name), "X11/%s", driver_descriptor.name);
-
- nplat->name = x11_name;
- nplat->create_probe = x11_create_probe;
- nplat->get_probe_result = x11_get_probe_result;
- nplat->create_display = native_create_display;
-}
-
-static struct native_platform x11_platform;
+static const struct native_platform x11_platform = {
+ "X11", /* name */
+ x11_create_probe,
+ x11_get_probe_result,
+ native_create_display
+};
const struct native_platform *
native_get_x11_platform(void)
{
- x11_init_platform(&x11_platform);
return &x11_platform;
}
struct native_display *
x11_create_ximage_display(Display *dpy,
- struct native_event_handler *event_handler);
+ struct native_event_handler *event_handler,
+ void *user_data);
struct native_display *
x11_create_dri2_display(Display *dpy,
- struct native_event_handler *event_handler);
+ struct native_event_handler *event_handler,
+ void *user_data);
#endif /* _NATIVE_X11_H_ */
struct native_display *
x11_create_ximage_display(Display *dpy,
- struct native_event_handler *event_handler)
+ struct native_event_handler *event_handler,
+ void *user_data)
{
struct ximage_display *xdpy;
struct sw_winsys *winsys = NULL;
}
xdpy->event_handler = event_handler;
+ xdpy->base.user_data = user_data;
xdpy->xscr_number = DefaultScreen(xdpy->dpy);
xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number);
if (!winsys)
goto fail;
- xdpy->base.screen = native_create_sw_screen(winsys);
+ xdpy->base.screen =
+ xdpy->event_handler->new_sw_screen(&xdpy->base, winsys);
if (!xdpy->base.screen)
goto fail;
TOP = ../../../..
include $(TOP)/configs/current
+ST_PREFIX := st_
+PIPE_PREFIX := egl_gallium_
+
common_CPPFLAGS := \
-I$(TOP)/src/gallium/auxiliary \
-I$(TOP)/src/gallium/drivers \
# EGL driver
egl_CPPFLAGS := \
-I$(TOP)/src/gallium/state_trackers/egl \
- -I$(TOP)/src/egl/main
+ -I$(TOP)/src/egl/main \
+ -DST_PREFIX=\"$(ST_PREFIX)\"
egl_SYS := -lm -ldl -lEGL
egl_LIBS := \
$(TOP)/src/gallium/state_trackers/egl/libegl.a \
egl_LIBS += $(TOP)/src/gallium/winsys/sw/fbdev/libfbdev.a
endif
+# EGL_RENDERABLE_TYPE is a compile time attribute
+egl_CPPFLAGS += $(API_DEFINES)
+ifneq ($(filter $(GL_LIB), $(EGL_CLIENT_APIS)),)
+egl_CPPFLAGS += -DFEATURE_GL=1
+endif
+ifneq ($(filter $(GLESv1_CM_LIB), $(EGL_CLIENT_APIS)),)
+egl_CPPFLAGS += -DFEATURE_ES1=1
+endif
+ifneq ($(filter $(GLESv2_LIB), $(EGL_CLIENT_APIS)),)
+egl_CPPFLAGS += -DFEATURE_ES2=1
+endif
+ifneq ($(filter $(VG_LIB), $(EGL_CLIENT_APIS)),)
+egl_CPPFLAGS += -DFEATURE_VG=1
+endif
+egl_CPPFLAGS := $(sort $(egl_CPPFLAGS))
+
# LLVM
ifeq ($(MESA_LLVM),1)
common_SYS += $(LLVM_LIBS)
OUTPUTS += vmwgfx
endif
OUTPUTS += swrast
-OUTPUTS := $(addprefix egl_gallium_, $(OUTPUTS))
+OUTPUTS := $(addprefix $(PIPE_PREFIX), $(OUTPUTS))
# state trackers
-OUTPUTS += $(addprefix st_, $(EGL_CLIENT_APIS))
+OUTPUTS += $(addprefix $(ST_PREFIX), $(EGL_CLIENT_APIS))
OUTPUTS := $(addsuffix .so, $(OUTPUTS))
OUTPUTS := $(addprefix $(OUTPUT_PATH)/, $(OUTPUTS))
define mklib-egl
$(MKLIB) -o $(notdir $@) -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \
- -install $(OUTPUT_PATH) $(MKLIB_OPTIONS) $< \
+ -install $(OUTPUT_PATH) $(MKLIB_OPTIONS) $< egl.o \
-Wl,--start-group $(common_LIBS) $(egl_LIBS) $($(1)_LIBS) -Wl,--end-group \
$(common_SYS) $(egl_SYS) $($(1)_SYS)
endef
endef
# EGL drivers
-$(OUTPUT_PATH)/egl_gallium_i915.so: pipe_i915.o $(egl_LIBS) $(i915_LIBS)
+$(OUTPUT_PATH)/$(PIPE_PREFIX)i915.so: pipe_i915.o egl.o $(egl_LIBS) $(i915_LIBS)
$(call mklib-egl,i915)
-$(OUTPUT_PATH)/egl_gallium_i965.so: pipe_i965.o $(egl_LIBS) $(i965_LIBS)
+$(OUTPUT_PATH)/$(PIPE_PREFIX)i965.so: pipe_i965.o egl.o $(egl_LIBS) $(i965_LIBS)
$(call mklib-egl,i965)
-$(OUTPUT_PATH)/egl_gallium_nouveau.so: pipe_nouveau.o $(egl_LIBS) $(nouveau_LIBS)
+$(OUTPUT_PATH)/$(PIPE_PREFIX)nouveau.so: pipe_nouveau.o egl.o $(egl_LIBS) $(nouveau_LIBS)
$(call mklib-egl,nouveau)
-$(OUTPUT_PATH)/egl_gallium_radeon.so: pipe_radeon.o $(egl_LIBS) $(radeon_LIBS)
+$(OUTPUT_PATH)/$(PIPE_PREFIX)radeon.so: pipe_radeon.o egl.o $(egl_LIBS) $(radeon_LIBS)
$(call mklib-egl,radeon)
-$(OUTPUT_PATH)/egl_gallium_vmwgfx.so: pipe_vmwgfx.o $(egl_LIBS) $(vmwgfx_LIBS)
+$(OUTPUT_PATH)/$(PIPE_PREFIX)vmwgfx.so: pipe_vmwgfx.o egl.o $(egl_LIBS) $(vmwgfx_LIBS)
$(call mklib-egl,vmwgfx)
-$(OUTPUT_PATH)/egl_gallium_swrast.so: pipe_swrast.o $(egl_LIBS) $(swrast_LIBS)
+$(OUTPUT_PATH)/$(PIPE_PREFIX)swrast.so: pipe_swrast.o egl.o $(egl_LIBS) $(swrast_LIBS)
$(call mklib-egl,swrast)
# state trackers
-$(OUTPUT_PATH)/st_$(GL_LIB).so: st_GL.o $(GL_LIBS)
+$(OUTPUT_PATH)/$(ST_PREFIX)$(GL_LIB).so: st_GL.o $(GL_LIBS)
$(call mklib,GL)
-$(OUTPUT_PATH)/st_$(GLESv1_CM_LIB).so: st_GLESv1_CM.o $(GLESv1_CM_LIBS)
+$(OUTPUT_PATH)/$(ST_PREFIX)$(GLESv1_CM_LIB).so: st_GLESv1_CM.o $(GLESv1_CM_LIBS)
$(call mklib,GLESv1_CM)
-$(OUTPUT_PATH)/st_$(GLESv2_LIB).so: st_GLESv2.o $(GLESv2_LIBS)
+$(OUTPUT_PATH)/$(ST_PREFIX)$(GLESv2_LIB).so: st_GLESv2.o $(GLESv2_LIBS)
$(call mklib,GLESv2)
-$(OUTPUT_PATH)/st_$(VG_LIB).so: st_OpenVG.o $(OpenVG_LIBS)
+$(OUTPUT_PATH)/$(ST_PREFIX)$(VG_LIB).so: st_OpenVG.o $(OpenVG_LIBS)
$(call mklib,OpenVG)
+egl.o: egl.c
+ $(CC) -c -o $@ $< $(common_CPPFLAGS) $(egl_CPPFLAGS) $(DEFINES) $(CFLAGS)
+
pipe_%.o: pipe_%.c
$(CC) -c -o $@ $< $(common_CPPFLAGS) $($*_CPPFLAGS) $(DEFINES) $(CFLAGS)
egl_gallium_swrast = env.SharedLibrary(
target ='egl_gallium_swrast',
- source = 'pipe_swrast.c',
+ source = ['egl.c', 'pipe_swrast.c'],
LIBS = st_egl_gdi + ws_gdi + drivers + gallium + egl + env['LIBS'],
)
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.9
+ *
+ * Copyright (C) 2010 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.
+ *
+ * Authors:
+ * Chia-I Wu <olv@lunarg.com>
+ */
+
+#include "util/u_debug.h"
+#include "util/u_string.h"
+#include "util/u_memory.h"
+#include "util/u_dl.h"
+#include "egldriver.h"
+#include "egllog.h"
+
+#include "state_tracker/st_api.h"
+#include "softpipe/sp_public.h"
+#include "llvmpipe/lp_public.h"
+#include "target-helpers/wrap_screen.h"
+#include "common/egl_g3d_loader.h"
+#include "state_tracker/drm_driver.h"
+
+struct egl_g3d_loader egl_g3d_loader;
+
+static struct st_module {
+ boolean initialized;
+ const char *name;
+ struct util_dl_library *lib;
+ struct st_api *stapi;
+} st_modules[ST_API_COUNT];
+
+static EGLBoolean
+dlopen_st_module_cb(const char *dir, size_t len, void *callback_data)
+{
+ struct st_module *stmod =
+ (struct st_module *) callback_data;
+ char path[1024];
+ int ret;
+
+ if (len) {
+ ret = util_snprintf(path, sizeof(path),
+ "%.*s/" ST_PREFIX "%s" UTIL_DL_EXT, len, dir, stmod->name);
+ }
+ else {
+ ret = util_snprintf(path, sizeof(path),
+ ST_PREFIX "%s" UTIL_DL_EXT, stmod->name);
+ }
+
+ if (ret > 0 && ret < sizeof(path)) {
+ stmod->lib = util_dl_open(path);
+ if (stmod->lib)
+ _eglLog(_EGL_DEBUG, "loaded %s", path);
+ }
+
+ return !(stmod->lib);
+}
+
+static boolean
+load_st_module(struct st_module *stmod,
+ const char *name, const char *procname)
+{
+ struct st_api *(*create_api)(void);
+
+ stmod->name = name;
+ if (stmod->name)
+ _eglSearchPathForEach(dlopen_st_module_cb, (void *) stmod);
+ else
+ stmod->lib = util_dl_open(NULL);
+
+ if (stmod->lib) {
+ create_api = (struct st_api *(*)(void))
+ util_dl_get_proc_address(stmod->lib, procname);
+ if (create_api)
+ stmod->stapi = create_api();
+
+ if (!stmod->stapi) {
+ util_dl_close(stmod->lib);
+ stmod->lib = NULL;
+ }
+ }
+
+ if (!stmod->stapi)
+ stmod->name = NULL;
+
+ return (stmod->stapi != NULL);
+}
+
+static struct st_api *
+get_st_api(enum st_api_type api)
+{
+ struct st_module *stmod = &st_modules[api];
+ const char *names[8], *symbol;
+ int i, count = 0;
+
+ if (stmod->initialized)
+ return stmod->stapi;
+
+ switch (api) {
+ case ST_API_OPENGL:
+ symbol = ST_CREATE_OPENGL_SYMBOL;
+ names[count++] = "GL";
+ break;
+ case ST_API_OPENGL_ES1:
+ symbol = ST_CREATE_OPENGL_ES1_SYMBOL;
+ names[count++] = "GLESv1_CM";
+ names[count++] = "GL";
+ break;
+ case ST_API_OPENGL_ES2:
+ symbol = ST_CREATE_OPENGL_ES2_SYMBOL;
+ names[count++] = "GLESv2";
+ names[count++] = "GL";
+ break;
+ case ST_API_OPENVG:
+ symbol = ST_CREATE_OPENVG_SYMBOL;
+ names[count++] = "OpenVG";
+ break;
+ default:
+ symbol = NULL;
+ assert(!"Unknown API Type\n");
+ break;
+ }
+
+ /* NULL means the process itself */
+ names[count++] = NULL;
+
+ for (i = 0; i < count; i++) {
+ if (load_st_module(stmod, names[i], symbol))
+ break;
+ }
+
+ if (!stmod->stapi) {
+ EGLint level = (egl_g3d_loader.api_mask & (1 << api)) ?
+ _EGL_WARNING : _EGL_DEBUG;
+ _eglLog(level, "unable to load " ST_PREFIX "%s" UTIL_DL_EXT, names[0]);
+ }
+
+ stmod->initialized = TRUE;
+
+ return stmod->stapi;
+}
+
+static struct st_api *
+guess_gl_api(void)
+{
+ struct st_api *stapi;
+ int gl_apis[] = {
+ ST_API_OPENGL,
+ ST_API_OPENGL_ES1,
+ ST_API_OPENGL_ES2,
+ -1
+ };
+ int i, api = -1;
+
+ /* determine the api from the loaded libraries */
+ for (i = 0; gl_apis[i] != -1; i++) {
+ if (st_modules[gl_apis[i]].stapi) {
+ api = gl_apis[i];
+ break;
+ }
+ }
+ /* determine the api from the linked libraries */
+ if (api == -1) {
+ struct util_dl_library *self = util_dl_open(NULL);
+
+ if (self) {
+ if (util_dl_get_proc_address(self, "glColor4d"))
+ api = ST_API_OPENGL;
+ else if (util_dl_get_proc_address(self, "glColor4x"))
+ api = ST_API_OPENGL_ES1;
+ else if (util_dl_get_proc_address(self, "glShaderBinary"))
+ api = ST_API_OPENGL_ES2;
+ util_dl_close(self);
+ }
+ }
+
+ stapi = (api != -1) ? get_st_api(api) : NULL;
+ if (!stapi) {
+ for (i = 0; gl_apis[i] != -1; i++) {
+ api = gl_apis[i];
+ stapi = get_st_api(api);
+ if (stapi)
+ break;
+ }
+ }
+
+ return stapi;
+}
+
+static struct pipe_screen *
+create_drm_screen(const char *name, int fd)
+{
+ return (driver_descriptor.driver_name && name &&
+ strcmp(driver_descriptor.driver_name, name) == 0) ?
+ driver_descriptor.create_screen(fd) : NULL;
+}
+
+static struct pipe_screen *
+create_sw_screen(struct sw_winsys *ws)
+{
+ struct pipe_screen *screen = NULL;
+
+#if defined(GALLIUM_LLVMPIPE)
+ if (!screen && !debug_get_bool_option("GALLIUM_NO_LLVM", FALSE))
+ screen = llvmpipe_create_screen(ws);
+#endif
+ if (!screen)
+ screen = softpipe_create_screen(ws);
+
+ return (screen) ? gallium_wrap_screen(screen) : NULL;
+}
+
+static const struct egl_g3d_loader *
+loader_init(void)
+{
+ uint api_mask = 0x0;
+
+ /* TODO detect at runtime? */
+#if FEATURE_GL
+ api_mask |= 1 << ST_API_OPENGL;
+#endif
+#if FEATURE_ES1
+ api_mask |= 1 << ST_API_OPENGL_ES1;
+#endif
+#if FEATURE_ES2
+ api_mask |= 1 << ST_API_OPENGL_ES2;
+#endif
+#if FEATURE_VG
+ api_mask |= 1 << ST_API_OPENVG;
+#endif
+
+ egl_g3d_loader.api_mask = api_mask;
+ egl_g3d_loader.get_st_api = get_st_api;
+ egl_g3d_loader.guess_gl_api = guess_gl_api;
+ egl_g3d_loader.create_drm_screen = create_drm_screen;
+ egl_g3d_loader.create_sw_screen = create_sw_screen;
+
+ return &egl_g3d_loader;
+}
+
+static void
+loader_fini(void)
+{
+ int i;
+
+ for (i = 0; i < ST_API_COUNT; i++) {
+ struct st_module *stmod = &st_modules[i];
+
+ if (stmod->stapi) {
+ stmod->stapi->destroy(stmod->stapi);
+ stmod->stapi = NULL;
+ }
+ if (stmod->lib) {
+ util_dl_close(stmod->lib);
+ stmod->lib = NULL;
+ }
+ stmod->name = NULL;
+ stmod->initialized = FALSE;
+ }
+}
+
+static void
+egl_g3d_unload(_EGLDriver *drv)
+{
+ egl_g3d_destroy_driver(drv);
+ loader_fini();
+}
+
+_EGLDriver *
+_eglMain(const char *args)
+{
+ const struct egl_g3d_loader *loader;
+ _EGLDriver *drv;
+
+ loader = loader_init();
+ drv = egl_g3d_create_driver(loader);
+ if (!drv) {
+ loader_fini();
+ return NULL;
+ }
+
+ drv->Name = "Gallium";
+ drv->Unload = egl_g3d_unload;
+
+ return drv;
+}
}
DRM_DRIVER_DESCRIPTOR("i965", "i965", create_screen)
-
-/* A poor man's --whole-archive for EGL drivers */
-void *_eglMain(void *);
-void *_eglWholeArchive = (void *) _eglMain;
}
DRM_DRIVER_DESCRIPTOR("nouveau", "nouveau", create_screen)
-
-/* A poor man's --whole-archive for EGL drivers */
-void *_eglMain(void *);
-void *_eglWholeArchive = (void *) _eglMain;
}
DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen)
-
-/* A poor man's --whole-archive for EGL drivers */
-void *_eglMain(void *);
-void *_eglWholeArchive = (void *) _eglMain;
#include "state_tracker/drm_driver.h"
DRM_DRIVER_DESCRIPTOR("swrast", NULL, NULL)
-
-/* A poor man's --whole-archive for EGL drivers */
-void *_eglMain(void *);
-void *_eglWholeArchive = (void *) _eglMain;
}
DRM_DRIVER_DESCRIPTOR("vmwgfx", "vmwgfx", create_screen)
-
-/* A poor man's --whole-archive for EGL drivers */
-void *_eglMain(void *);
-void *_eglWholeArchive = (void *) _eglMain;