st/egl: Move module loading code to targets.

Several changes are made.  libegl.a no longer defines _eglMain.  It
defines functions to create and destroy a _EGLDriver instead.  The
creation function is called by the targets.  It takes an egl_g3d_loader
as its argument.  The loader is defined by the targets and is in charge
of creating st_api and pipe_screen.  This allows us to move the module
loading code to targets.  Lastly, the modules are now loaded as the
respective contexts are created.
diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile
index e117f15..9e9e479 100644
--- a/src/gallium/state_trackers/egl/Makefile
+++ b/src/gallium/state_trackers/egl/Makefile
@@ -5,14 +5,12 @@
 	-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 \
@@ -31,7 +29,7 @@
 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)
 
@@ -40,7 +38,7 @@
 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)),)
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c
index 36354dd..494d6dd 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.c
@@ -35,34 +35,10 @@
 #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.
  */
 static const struct native_platform *
@@ -323,7 +299,6 @@
                     _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;
@@ -347,7 +322,7 @@
    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)
@@ -472,8 +447,26 @@
       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
@@ -529,20 +522,25 @@
       _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) {
@@ -583,22 +581,15 @@
 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);
+   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();
 
-   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;
-      }
-   }
-
-   return (_EGLProc) NULL;
+   return (_EGLProc) ((stapi) ?
+         stapi->get_proc_address(stapi, procname) : NULL);
 }
 
 static EGLint
@@ -628,18 +619,8 @@
    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;
 
@@ -647,17 +628,28 @@
    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);
+}
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h
index a498dcf..d9ecb20 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d.h
+++ b/src/gallium/state_trackers/egl/common/egl_g3d.h
@@ -41,12 +41,11 @@
 
 #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;
 };
@@ -54,6 +53,7 @@
 struct egl_g3d_display {
    struct native_display *native;
 
+   const struct egl_g3d_loader *loader;
    struct st_manager *smapi;
    struct pipe_context *pipe;
 };
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
index 255a1fb..308fa96 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c
@@ -35,6 +35,7 @@
 #include "egl_g3d_api.h"
 #include "egl_g3d_image.h"
 #include "egl_g3d_st.h"
+#include "egl_g3d_loader.h"
 #include "native.h"
 
 /**
@@ -44,7 +45,6 @@
 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) {
@@ -73,8 +73,7 @@
       break;
    }
 
-   stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL;
-   return stapi;
+   return (idx >= 0) ? gdrv->loader->get_st_api(idx) : NULL;
 }
 
 static _EGLContext *
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_loader.h b/src/gallium/state_trackers/egl/common/egl_g3d_loader.h
new file mode 100644
index 0000000..c9141f8
--- /dev/null
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_loader.h
@@ -0,0 +1,54 @@
+/*
+ * 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_ */
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c
index 0668f5c..05cdb0d 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_st.c
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c
@@ -49,173 +49,6 @@
    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,
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.h b/src/gallium/state_trackers/egl/common/egl_g3d_st.h
index ee53799..aa25cc0 100644
--- a/src/gallium/state_trackers/egl/common/egl_g3d_st.h
+++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.h
@@ -33,12 +33,6 @@
 #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);
 
diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h
index c4d23bf..7e84d74 100644
--- a/src/gallium/state_trackers/egl/common/native.h
+++ b/src/gallium/state_trackers/egl/common/native.h
@@ -32,6 +32,7 @@
 #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"
@@ -196,6 +197,11 @@
    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);
 };
 
 /**
@@ -225,7 +231,8 @@
    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 *
diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c
index 206817e..7832b2b 100644
--- a/src/gallium/state_trackers/egl/common/native_helper.c
+++ b/src/gallium/state_trackers/egl/common/native_helper.c
@@ -31,9 +31,6 @@
 #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"
 
@@ -236,18 +233,3 @@
 
    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;
-}
diff --git a/src/gallium/state_trackers/egl/common/native_helper.h b/src/gallium/state_trackers/egl/common/native_helper.h
index bdb9629..d1569ac 100644
--- a/src/gallium/state_trackers/egl/common/native_helper.h
+++ b/src/gallium/state_trackers/egl/common/native_helper.h
@@ -69,6 +69,3 @@
 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);
diff --git a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c
index c0bc7b2..7c276c2 100644
--- a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c
+++ b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c
@@ -386,8 +386,10 @@
       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,
@@ -402,7 +404,8 @@
 }
 
 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;
 
@@ -412,6 +415,7 @@
 
    fbdpy->fd = fd;
    fbdpy->event_handler = event_handler;
+   fbdpy->base.user_data = user_data;
 
    if (!fbdev_display_init(&fbdpy->base)) {
       FREE(fbdpy);
@@ -428,7 +432,8 @@
 }
 
 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;
@@ -443,7 +448,7 @@
    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);
 
diff --git a/src/gallium/state_trackers/egl/gdi/native_gdi.c b/src/gallium/state_trackers/egl/gdi/native_gdi.c
index 4ec229a..ed955c4 100644
--- a/src/gallium/state_trackers/egl/gdi/native_gdi.c
+++ b/src/gallium/state_trackers/egl/gdi/native_gdi.c
@@ -343,10 +343,11 @@
 }
 
 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)
@@ -354,8 +355,21 @@
 
    gdpy->hDC = hDC;
    gdpy->event_handler = event_handler;
+   gdpy->base.user_data = user_data;
 
-   gdpy->base.screen = screen;
+   winsys = gdi_create_sw_winsys();
+   if (!winsys) {
+      FREE(gdpy);
+      return NULL;
+   }
+
+   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;
@@ -367,23 +381,10 @@
 }
 
 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 = {
diff --git a/src/gallium/state_trackers/egl/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c
index dd4ea71..5833d27 100644
--- a/src/gallium/state_trackers/egl/kms/native_kms.c
+++ b/src/gallium/state_trackers/egl/kms/native_kms.c
@@ -23,6 +23,10 @@
  * 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"
@@ -33,7 +37,6 @@
 #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,
@@ -656,7 +659,7 @@
       kdpy->base.screen->destroy(kdpy->base.screen);
 
    if (kdpy->fd >= 0)
-      drmClose(kdpy->fd);
+      close(kdpy->fd);
 
    FREE(kdpy);
 }
@@ -668,50 +671,23 @@
 kms_display_init_screen(struct native_display *ndpy)
 {
    struct kms_display *kdpy = kms_display(ndpy);
-   int fd;
+   drmVersionPtr version;
 
-   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;
-      }
-
-      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;
 }
 
@@ -723,7 +699,8 @@
 };
 
 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;
 
@@ -731,8 +708,10 @@
    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;
@@ -769,39 +748,32 @@
 }
 
 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);
+   if (dpy) {
+      fd = dup((int) pointer_to_intptr(dpy));
+   }
+   else {
+      fd = open("/dev/dri/card0", O_RDWR);
+   }
+   if (fd < 0)
+      return NULL;
 
-   return ndpy;
+   return kms_create_display(fd, event_handler, user_data);
 }
 
-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);
-
-   nplat->name = kms_name;
-   nplat->create_probe = NULL;
-   nplat->get_probe_result = NULL;
-   nplat->create_display = native_create_display;
-}
-
-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;
 }
diff --git a/src/gallium/state_trackers/egl/kms/native_kms.h b/src/gallium/state_trackers/egl/kms/native_kms.h
index 14cf5a6..cd8e4ff 100644
--- a/src/gallium/state_trackers/egl/kms/native_kms.h
+++ b/src/gallium/state_trackers/egl/kms/native_kms.h
@@ -32,6 +32,7 @@
 #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"
diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c
index 7464354..1bef59d 100644
--- a/src/gallium/state_trackers/egl/x11/native_dri2.c
+++ b/src/gallium/state_trackers/egl/x11/native_dri2.c
@@ -692,7 +692,6 @@
 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) ||
@@ -703,19 +702,15 @@
 
    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;
@@ -739,7 +734,8 @@
 
 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;
 
@@ -748,6 +744,7 @@
       return NULL;
 
    dri2dpy->event_handler = event_handler;
+   dri2dpy->base.user_data = user_data;
 
    dri2dpy->dpy = dpy;
    if (!dri2dpy->dpy) {
diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c
index 7eec563..f051940 100644
--- a/src/gallium/state_trackers/egl/x11/native_x11.c
+++ b/src/gallium/state_trackers/egl/x11/native_x11.c
@@ -23,7 +23,6 @@
  * DEALINGS IN THE SOFTWARE.
  */
 
-#include <string.h>
 #include "util/u_debug.h"
 #include "util/u_memory.h"
 #include "util/u_string.h"
@@ -107,50 +106,38 @@
 }
 
 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;
 }
diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h
index a1c32c3..0b47837 100644
--- a/src/gallium/state_trackers/egl/x11/native_x11.h
+++ b/src/gallium/state_trackers/egl/x11/native_x11.h
@@ -30,10 +30,12 @@
 
 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_ */
diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c
index ee10a04..4b32f6e 100644
--- a/src/gallium/state_trackers/egl/x11/native_ximage.c
+++ b/src/gallium/state_trackers/egl/x11/native_ximage.c
@@ -442,7 +442,8 @@
 
 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;
@@ -462,6 +463,7 @@
    }
 
    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);
@@ -472,7 +474,8 @@
    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;
 
diff --git a/src/gallium/targets/egl/Makefile b/src/gallium/targets/egl/Makefile
index 364a31d..80f9c60 100644
--- a/src/gallium/targets/egl/Makefile
+++ b/src/gallium/targets/egl/Makefile
@@ -15,6 +15,9 @@
 TOP = ../../../..
 include $(TOP)/configs/current
 
+ST_PREFIX := st_
+PIPE_PREFIX := egl_gallium_
+
 common_CPPFLAGS := \
 	-I$(TOP)/src/gallium/auxiliary \
 	-I$(TOP)/src/gallium/drivers \
@@ -30,7 +33,8 @@
 # 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 \
@@ -47,6 +51,22 @@
 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)
@@ -136,10 +156,10 @@
 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))
@@ -148,7 +168,7 @@
 
 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
@@ -161,37 +181,40 @@
 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)
 
diff --git a/src/gallium/targets/egl/SConscript b/src/gallium/targets/egl/SConscript
index c743c26..f2bcb6e 100644
--- a/src/gallium/targets/egl/SConscript
+++ b/src/gallium/targets/egl/SConscript
@@ -27,7 +27,7 @@
 
     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'],
     )
 
diff --git a/src/gallium/targets/egl/egl.c b/src/gallium/targets/egl/egl.c
new file mode 100644
index 0000000..831adf7
--- /dev/null
+++ b/src/gallium/targets/egl/egl.c
@@ -0,0 +1,305 @@
+/*
+ * 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;
+}
diff --git a/src/gallium/targets/egl/pipe_i965.c b/src/gallium/targets/egl/pipe_i965.c
index d19c83a..cf96214 100644
--- a/src/gallium/targets/egl/pipe_i965.c
+++ b/src/gallium/targets/egl/pipe_i965.c
@@ -28,7 +28,3 @@
 }
 
 DRM_DRIVER_DESCRIPTOR("i965", "i965", create_screen)
-
-/* A poor man's --whole-archive for EGL drivers */
-void *_eglMain(void *);
-void *_eglWholeArchive = (void *) _eglMain;
diff --git a/src/gallium/targets/egl/pipe_nouveau.c b/src/gallium/targets/egl/pipe_nouveau.c
index cf569ea..e725a4d 100644
--- a/src/gallium/targets/egl/pipe_nouveau.c
+++ b/src/gallium/targets/egl/pipe_nouveau.c
@@ -18,7 +18,3 @@
 }
 
 DRM_DRIVER_DESCRIPTOR("nouveau", "nouveau", create_screen)
-
-/* A poor man's --whole-archive for EGL drivers */
-void *_eglMain(void *);
-void *_eglWholeArchive = (void *) _eglMain;
diff --git a/src/gallium/targets/egl/pipe_radeon.c b/src/gallium/targets/egl/pipe_radeon.c
index ce07327..5a0a8dc 100644
--- a/src/gallium/targets/egl/pipe_radeon.c
+++ b/src/gallium/targets/egl/pipe_radeon.c
@@ -24,7 +24,3 @@
 }
 
 DRM_DRIVER_DESCRIPTOR("radeon", "radeon", create_screen)
-
-/* A poor man's --whole-archive for EGL drivers */
-void *_eglMain(void *);
-void *_eglWholeArchive = (void *) _eglMain;
diff --git a/src/gallium/targets/egl/pipe_swrast.c b/src/gallium/targets/egl/pipe_swrast.c
index d8205c1..1ad4e25 100644
--- a/src/gallium/targets/egl/pipe_swrast.c
+++ b/src/gallium/targets/egl/pipe_swrast.c
@@ -2,7 +2,3 @@
 #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;
diff --git a/src/gallium/targets/egl/pipe_vmwgfx.c b/src/gallium/targets/egl/pipe_vmwgfx.c
index 4e9f51c..15089d6 100644
--- a/src/gallium/targets/egl/pipe_vmwgfx.c
+++ b/src/gallium/targets/egl/pipe_vmwgfx.c
@@ -24,7 +24,3 @@
 }
 
 DRM_DRIVER_DESCRIPTOR("vmwgfx", "vmwgfx", create_screen)
-
-/* A poor man's --whole-archive for EGL drivers */
-void *_eglMain(void *);
-void *_eglWholeArchive = (void *) _eglMain;