Simplify dri loading code by eliminating dlopen "cache".
authorKristian Høgsberg <krh@redhat.com>
Fri, 7 Mar 2008 06:37:08 +0000 (01:37 -0500)
committerKristian Høgsberg <krh@redhat.com>
Sat, 8 Mar 2008 21:19:39 +0000 (16:19 -0500)
No need to jump through hoops to track __DRIdrivers and avoid dlopening the
same .so more than twice, dlopen() does this internally.  Besides, we
were already bypassing this and dlopening drivers for each screen,
whether or not they were already dlopened.

src/glx/x11/dri_glx.c
src/glx/x11/dri_glx.h
src/glx/x11/glxclient.h
src/glx/x11/glxext.c

index c84e384..078c9b6 100644 (file)
@@ -66,13 +66,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DEFAULT_DRIVER_DIR "/usr/X11R6/lib/modules/dri"
 #endif
 
-static __DRIdriver *Drivers = NULL;
-
-
-/*
- * printf wrappers
- */
-
 static void InfoMessageF(const char *f, ...)
 {
     va_list args;
@@ -187,22 +180,14 @@ static const char createNewScreenName[] = __DRI_CREATE_NEW_SCREEN_STRING;
  * \returns
  * A handle from \c dlopen, or \c NULL if driver file not found.
  */
-static __DRIdriver *OpenDriver(const char *driverName)
+static void *OpenDriver(const char *driverName)
 {
    void *glhandle = NULL;
    char *libPaths = NULL;
    char libDir[1000];
+   char realDriverName[200];
+   void *handle = NULL;
    int i;
-   __DRIdriver *driver;
-
-   /* First, search Drivers list to see if we've already opened this driver */
-   for (driver = Drivers; driver; driver = driver->next) {
-      if (strcmp(driver->name, driverName) == 0) {
-         /* found it, increment library refcount & return */
-         dlopen(driver->libpath, RTLD_NOW | RTLD_GLOBAL);
-         return driver;
-      }
-   }
 
    /* Attempt to make sure libGL symbols will be visible to the driver */
    glhandle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL);
@@ -217,10 +202,6 @@ static __DRIdriver *OpenDriver(const char *driverName)
       libPaths = DEFAULT_DRIVER_DIR;
 
    for ( i = 0 ; ExtractDir(i, libPaths, 1000, libDir) != 0 ; i++ ) {
-      char realDriverName[200];
-      void *handle = NULL;
-
-      
       /* If TLS support is enabled, try to open the TLS version of the driver
        * binary first.  If that fails, try the non-TLS version.
        */
@@ -236,57 +217,19 @@ static __DRIdriver *OpenDriver(const char *driverName)
         handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
       }
 
-      if ( handle != NULL ) {
-         /* allocate __DRIdriver struct */
-         driver = (__DRIdriver *) Xmalloc(sizeof(__DRIdriver));
-         if (!driver)
-            break; /* out of memory! */
-         /* init the struct */
-         driver->name = __glXstrdup(driverName);
-         driver->libpath = __glXstrdup(realDriverName);
-         if (!driver->name || !driver->libpath) {
-            if (driver->name)
-               Xfree(driver->name);
-            if (driver->libpath)
-               Xfree(driver->libpath);
-            Xfree(driver);
-            driver = NULL;
-            break; /* out of memory! */
-         }
-
-         driver->createNewScreenFunc = (PFNCREATENEWSCREENFUNC)
-            dlsym(handle, createNewScreenName);
-
-         if ( driver->createNewScreenFunc == NULL ) {
-            /* If the driver doesn't have this symbol then something's
-             * really, really wrong.
-             */
-            ErrorMessageF("%s not defined in %s_dri.so!\n"
-                         "Your driver may be too old for this libGL.\n",
-                         createNewScreenName, driverName);
-            Xfree(driver);
-            driver = NULL;
-            dlclose(handle);
-            continue;
-         }
-         driver->handle = handle;
-         /* put at head of linked list */
-         driver->next = Drivers;
-         Drivers = driver;
-         break;
-      }
-      else {
+      if ( handle != NULL )
+         break;
+      else
         ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
-      }
    }
 
-   if (!driver)
+   if (!handle)
       ErrorMessageF("unable to load driver: %s_dri.so\n", driverName);
 
    if (glhandle)
       dlclose(glhandle);
 
-   return driver;
+   return handle;
 }
 
 
@@ -330,11 +273,12 @@ static Bool GetDriverName(Display *dpy, int scrNum, char **driverName)
  * Given a display pointer and screen number, return a __DRIdriver handle.
  * Return NULL if anything goes wrong.
  */
-__DRIdriver *driGetDriver(Display *dpy, int scrNum)
+static void *driGetDriver(Display *dpy, int scrNum)
 {
    char *driverName;
+   void *ret;
+
    if (GetDriverName(dpy, scrNum, &driverName)) {
-      __DRIdriver *ret;
       ret = OpenDriver(driverName);
       if (driverName)
         Xfree(driverName);
@@ -343,7 +287,6 @@ __DRIdriver *driGetDriver(Display *dpy, int scrNum)
    return NULL;
 }
 
-
 /*
  * Exported function for querying the DRI driver for a given screen.
  *
@@ -380,9 +323,9 @@ PUBLIC const char *glXGetScreenDriver (Display *dpy, int scrNum) {
  * Note: The driver remains opened after this function returns.
  */
 PUBLIC const char *glXGetDriverConfig (const char *driverName) {
-   __DRIdriver *driver = OpenDriver (driverName);
-   if (driver)
-      return dlsym (driver->handle, "__driConfigOptions");
+   void *handle = OpenDriver (driverName);
+   if (handle)
+      return dlsym (handle, "__driConfigOptions");
    else
       return NULL;
 }
@@ -564,7 +507,6 @@ static const __DRIextension *loader_extensions[] = {
 };
 
 
-
 /**
  * Perform the required libGL-side initialization and call the client-side
  * driver's \c __driCreateNewScreen function.
@@ -766,6 +708,11 @@ void
 driCreateScreen(__GLXscreenConfigs *psc, int screen,
                __GLXdisplayPrivate *priv)
 {
+    PFNCREATENEWSCREENFUNC createNewScreen;
+
+    if (priv->driDisplay.private == NULL)
+       return;
+
     /* Create drawable hash */
     psc->drawHash = __glxHashCreate();
     if ( psc->drawHash == NULL )
@@ -773,22 +720,29 @@ driCreateScreen(__GLXscreenConfigs *psc, int screen,
 
     /* Initialize per screen dynamic client GLX extensions */
     psc->ext_list_first_time = GL_TRUE;
-    /* Initialize the direct rendering per screen data and functions */
-    if (priv->driDisplay.private != NULL) {
-       /* FIXME: Should it be some sort of an error if createNewScreen[i]
-        * FIXME: is NULL?
-        */
-       if (priv->driDisplay.createNewScreen &&
-           priv->driDisplay.createNewScreen[screen]) {
-
-           psc->driScreen.private =
-               CallCreateNewScreen(psc->dpy, screen, psc,
-                                   & priv->driDisplay,
-                                   priv->driDisplay.createNewScreen[screen] );
-           if (psc->driScreen.private != NULL)
-               __glXScrEnableDRIExtension(psc);
-       }
-    }
+
+    psc->driver = driGetDriver(priv->dpy, screen);
+    createNewScreen = dlsym(psc->driver, createNewScreenName);
+    if (createNewScreenName == NULL)
+       return;
+
+    psc->driScreen.private =
+       CallCreateNewScreen(psc->dpy, screen, psc,
+                           &priv->driDisplay, createNewScreen);
+    if (psc->driScreen.private != NULL)
+       __glXScrEnableDRIExtension(psc);
+}
+
+void driDestroyScreen(__GLXscreenConfigs *psc)
+{
+    /* Free the direct rendering per screen data */
+    if (psc->driScreen.private)
+       (*psc->driScreen.destroyScreen)(&psc->driScreen);
+    psc->driScreen.private = NULL;
+    if (psc->drawHash)
+       __glxHashDestroy(psc->drawHash);
+    if (psc->driver)
+       dlclose(psc->driver);
 }
 
 /* Called from __glXFreeDisplayPrivate.
@@ -797,35 +751,8 @@ static void driDestroyDisplay(Display *dpy, void *private)
 {
     __DRIdisplayPrivate *pdpyp = (__DRIdisplayPrivate *)private;
 
-    if (pdpyp) {
-        const int numScreens = ScreenCount(dpy);
-        int i;
-        for (i = 0; i < numScreens; i++) {
-          if (pdpyp->libraryHandles[i]) {
-             __DRIdriver *driver, *prev;
-
-             /* Remove driver from Drivers list */
-             for (prev = NULL, driver = Drivers; driver;
-                  prev = driver, driver = driver->next) {
-                if (driver->handle == pdpyp->libraryHandles[i]) {
-                   if (prev)
-                      prev->next = driver->next;
-                   else
-                      Drivers = driver->next;
-
-                   Xfree(driver->name);
-                   Xfree(driver->libpath);
-                   Xfree(driver);
-                   break;
-                }
-             }
-
-             dlclose(pdpyp->libraryHandles[i]);
-          }
-        }
-        Xfree(pdpyp->libraryHandles);
+    if (pdpyp)
        Xfree(pdpyp);
-    }
 }
 
 
@@ -836,11 +763,9 @@ static void driDestroyDisplay(Display *dpy, void *private)
  */
 void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp)
 {
-    const int numScreens = ScreenCount(dpy);
     __DRIdisplayPrivate *pdpyp;
     int eventBase, errorBase;
     int major, minor, patch;
-    int scrn;
 
     /* Initialize these fields to NULL in case we fail.
      * If we don't do this we may later get segfaults trying to free random
@@ -868,38 +793,6 @@ void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp)
 
     pdisp->destroyDisplay = driDestroyDisplay;
 
-    /* allocate array of pointers to createNewScreen funcs */
-    pdisp->createNewScreen = (PFNCREATENEWSCREENFUNC *)
-      Xmalloc(numScreens * sizeof(void *));
-    if (!pdisp->createNewScreen) {
-       Xfree(pdpyp);
-       return NULL;
-    }
-
-    /* allocate array of library handles */
-    pdpyp->libraryHandles = (void **) Xmalloc(numScreens * sizeof(void*));
-    if (!pdpyp->libraryHandles) {
-       Xfree(pdisp->createNewScreen);
-       Xfree(pdpyp);
-       return NULL;
-    }
-
-    /* dynamically discover DRI drivers for all screens, saving each
-     * driver's "__driCreateScreen" function pointer.  That's the bootstrap
-     * entrypoint for all DRI drivers.
-     */
-    for (scrn = 0; scrn < numScreens; scrn++) {
-        __DRIdriver *driver = driGetDriver(dpy, scrn);
-        if (driver) {
-           pdisp->createNewScreen[scrn] = driver->createNewScreenFunc;
-           pdpyp->libraryHandles[scrn] = driver->handle;
-        }
-        else {
-           pdisp->createNewScreen[scrn] = NULL;
-           pdpyp->libraryHandles[scrn] = NULL;
-        }
-    }
-
     return (void *)pdpyp;
 }
 
index 7556168..4dd62ed 100644 (file)
@@ -44,11 +44,6 @@ struct __DRIdisplayPrivateRec {
     int driMajor;
     int driMinor;
     int driPatch;
-
-    /*
-    ** Array of library handles [indexed by screen number]
-    */
-    void **libraryHandles;
 };
 
 typedef struct __DRIdisplayPrivateRec  __DRIdisplayPrivate;
index a1fff0a..e62eec8 100644 (file)
@@ -103,24 +103,6 @@ struct __DRIdisplayRec {
      * \c NULL if direct rendering is not supported on this display.
      */
     struct __DRIdisplayPrivateRec *private;
-
-    /**
-     * Array of pointers to methods to create and initialize the private DRI
-     * screen data.
-     */
-    PFNCREATENEWSCREENFUNC * createNewScreen;
-};
-
-
-/*
-** We keep a linked list of these structures, one per DRI device driver.
-*/
-struct __DRIdriverRec {
-   const char *name;
-   const char *libpath;
-   void *handle;
-   PFNCREATENEWSCREENFUNC createNewScreenFunc;
-   struct __DRIdriverRec *next;
 };
 
 /*
@@ -130,8 +112,7 @@ struct __DRIdriverRec {
 extern void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp);
 extern void driCreateScreen(__GLXscreenConfigs *psc, int screen,
                            __GLXdisplayPrivate *priv);
-
-extern  __DRIdriver *driGetDriver(Display *dpy, int scrNum);
+extern void driDestroyScreen(__GLXscreenConfigs *psc);
 
 extern void DRI_glXUseXFont( Font font, int first, int count, int listbase );
 
@@ -458,6 +439,7 @@ struct __GLXscreenConfigsRec {
     __glxHashTable *drawHash;
     Display *dpy;
     int scr;
+    void *driver;
 
 #ifdef __DRI_COPY_SUB_BUFFER
     __DRIcopySubBufferExtension *copySubBuffer;
index e073122..61352a6 100644 (file)
@@ -358,12 +358,7 @@ static void FreeScreenConfigs(__GLXdisplayPrivate *priv)
        Xfree((char*) psc->serverGLXexts);
 
 #ifdef GLX_DIRECT_RENDERING
-       /* Free the direct rendering per screen data */
-       if (psc->driScreen.private)
-           (*psc->driScreen.destroyScreen)(&psc->driScreen);
-       psc->driScreen.private = NULL;
-       if (psc->drawHash)
-           __glxHashDestroy(psc->drawHash);
+       driDestroyScreen(psc);
 #endif
     }
     XFree((char*) priv->screenConfigs);
@@ -394,10 +389,6 @@ static int __glXFreeDisplayPrivate(XExtData *extension)
        (*priv->driDisplay.destroyDisplay)(priv->dpy,
                                           priv->driDisplay.private);
     priv->driDisplay.private = NULL;
-    if (priv->driDisplay.createNewScreen) {
-        Xfree(priv->driDisplay.createNewScreen); /* free array of ptrs */
-        priv->driDisplay.createNewScreen = NULL;
-    }
 #endif
 
     Xfree((char*) priv);