/**
 * Invoke a callback function on each EGL search path.
 *
 * The first argument of the callback function is the name of the search path.
 * The second argument is the length of the name.
 */
void
_eglSearchPathForEach(EGLBoolean (*callback)(const char *, size_t, void *),
                      void *callback_data)
{
   const char *search_path = _eglGetSearchPath();
   _eglPreloadForEach(search_path, callback, callback_data);
}
/**
 * Add egl_gallium to the module array.
 */
static void
_eglAddGalliumDriver(void)
{
#ifndef _EGL_BUILT_IN_DRIVER_GALLIUM
   void *external = (void *) "egl_gallium";
   _eglPreloadForEach(_eglGetSearchPath(), _eglLoaderFile, external);
#endif
}
/**
 * Add the user driver to the module array.
 *
 * The user driver is specified by EGL_DRIVER.
 */
static EGLBoolean
_eglAddUserDriver(void)
{
   const char *search_path = _eglGetSearchPath();
   char *env;
   size_t name_len = 0;

   env = getenv("EGL_DRIVER");
#if defined(_EGL_OS_UNIX)
   if (env && strchr(env, '/')) {
      search_path = "";
      if ((geteuid() != getuid() || getegid() != getgid())) {
         _eglLog(_EGL_DEBUG,
               "ignore EGL_DRIVER for setuid/setgid binaries");
         env = NULL;
      }
   }
   else if (env) {
      char *suffix = strchr(env, '.');
      name_len = (suffix) ? suffix - env : strlen(env);
   }
#else
   if (env)
      name_len = strlen(env);
#endif /* _EGL_OS_UNIX */

   /*
    * Try built-in drivers first if we know the driver name.  This makes sure
    * we do not load the outdated external driver that is still on the
    * filesystem.
    */
   if (name_len) {
      _EGLModule *mod;
      EGLint i;

      for (i = 0; _eglBuiltInDrivers[i].name; i++) {
         if (strlen(_eglBuiltInDrivers[i].name) == name_len &&
             !strncmp(_eglBuiltInDrivers[i].name, env, name_len)) {
            mod = _eglAddModule(env);
            if (mod)
               mod->BuiltIn = _eglBuiltInDrivers[i].main;

            return EGL_TRUE;
         }
      }
   }

   /* otherwise, treat env as a path */
   if (env) {
      _eglPreloadForEach(search_path, _eglLoaderFile, (void *) env);

      return EGL_TRUE;
   }

   return EGL_FALSE;
}
/**
 * Add drivers to the module array.  Drivers will be loaded as they are matched
 * to displays.
 */
static EGLBoolean
_eglAddDrivers(void)
{
   if (_eglModules)
      return EGL_TRUE;

   /* the order here decides the priorities of the drivers */
   _eglAddUserDriver();
   _eglAddDefaultDrivers();
   _eglPreloadForEach(_eglGetSearchPath(), _eglLoaderPattern, (void *) "egl_");

   return (_eglModules != NULL);
}
/**
 * Add the user driver to the module array.
 *
 * The user driver is specified by EGL_DRIVER.
 */
static void
_eglAddUserDriver(void)
{
   const char *search_path = _eglGetSearchPath();
   char *env;

   env = getenv("EGL_DRIVER");
#if defined(_EGL_OS_UNIX)
   if (env && strchr(env, '/')) {
      search_path = "";
      if ((geteuid() != getuid() || getegid() != getgid())) {
         _eglLog(_EGL_DEBUG,
               "ignore EGL_DRIVER for setuid/setgid binaries");
         env = NULL;
      }
   }
#endif /* _EGL_OS_UNIX */
   if (env)
      _eglPreloadForEach(search_path, _eglLoaderFile, (void *) env);
}
/**
 * Add default drivers to the module array.
 */
static void
_eglAddDefaultDrivers(void)
{
   const char *search_path = _eglGetSearchPath();
   EGLint i;
#if defined(_EGL_OS_WINDOWS)
   const char *DefaultDriverNames[] = {
      "egl_gallium"
   };
#elif defined(_EGL_OS_UNIX)
   const char *DefaultDriverNames[] = {
      "egl_gallium",
      "egl_dri2",
      "egl_glx"
   };
#endif

   for (i = 0; i < ARRAY_SIZE(DefaultDriverNames); i++) {
      void *name = (void *) DefaultDriverNames[i];
      _eglPreloadForEach(search_path, _eglLoaderFile, name);
   }
}