Example #1
0
/*
 * Given a display pointer and screen number, determine the name of
 * the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
 * Return True for success, False for failure.
 */
static Bool GetDriverName(Display *dpy, int scrNum, char **driverName)
{
   int directCapable;
   Bool b;
   int driverMajor, driverMinor, driverPatch;

   *driverName = NULL;

   if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
      ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
      return False;
   }
   if (!directCapable) {
      ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
      return False;
   }

   b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
                                  &driverPatch, driverName);
   if (!b) {
      ErrorMessageF("Cannot determine driver name for screen %d\n", scrNum);
      return False;
   }

   InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
	     driverMajor, driverMinor, driverPatch, *driverName, scrNum);

   return True;
}
Example #2
0
_X_HIDDEN __GLXDRIdrawable *
driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
{
   struct glx_display *const priv = __glXInitialize(gc->psc->dpy);
   __GLXDRIdrawable *pdraw;
   struct glx_screen *psc;

   if (priv == NULL)
      return NULL;

   psc = priv->screens[gc->screen];
   if (priv->drawHash == NULL)
      return NULL;

   if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) {
      pdraw->refcount ++;
      return pdraw;
   }

   pdraw = psc->driScreen->createDrawable(psc, glxDrawable,
                                          glxDrawable, gc->config);

   if (pdraw == NULL) {
      ErrorMessageF("failed to create drawable\n");
      return NULL;
   }

   if (__glxHashInsert(priv->drawHash, glxDrawable, pdraw)) {
      (*pdraw->destroyDrawable) (pdraw);
      return NULL;
   }
   pdraw->refcount = 1;

   return pdraw;
}
Example #3
0
/*
 * Given a display pointer and screen number, determine the name of
 * the DRI driver for the screen (i.e., "i965", "radeon", "nouveau", etc).
 * Return True for success, False for failure.
 */
static Bool
driGetDriverName(Display * dpy, int scrNum, char **driverName)
{
   int directCapable;
   Bool b;
   int event, error;
   int driverMajor, driverMinor, driverPatch;

   *driverName = NULL;

   if (XF86DRIQueryExtension(dpy, &event, &error)) {    /* DRI1 */
      if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
         ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
         return False;
      }
      if (!directCapable) {
         ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
         return False;
      }

      b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
                                     &driverPatch, driverName);
      if (!b) {
         ErrorMessageF("Cannot determine driver name for screen %d\n",
                       scrNum);
         return False;
      }

      InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
                   driverMajor, driverMinor, driverPatch, *driverName,
                   scrNum);

      return True;
   }
   else if (DRI2QueryExtension(dpy, &event, &error)) {  /* DRI2 */
      char *dev;
      Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev);

      if (ret)
         free(dev);

      return ret;
   }

   return False;
}
Example #4
0
/**
 * Perform the required libGL-side initialization and call the client-side
 * driver's \c __driCreateNewScreen function.
 * 
 * \param dpy    Display pointer.
 * \param scrn   Screen number on the display.
 * \param psc    DRI screen information.
 * \param driDpy DRI display information.
 * \param createNewScreen  Pointer to the client-side driver's
 *               \c __driCreateNewScreen function.
 * \returns A pointer to the \c __DRIscreen structure returned by
 *          the client-side driver on success, or \c NULL on failure.
 */
static void *
CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc,
                    struct dri_display * driDpy)
{
   void *psp = NULL;
   drm_handle_t hSAREA;
   drmAddress pSAREA = MAP_FAILED;
   char *BusID;
   __DRIversion ddx_version;
   __DRIversion dri_version;
   __DRIversion drm_version;
   __DRIframebuffer framebuffer;
   int fd = -1;
   int status;

   drm_magic_t magic;
   drmVersionPtr version;
   int newlyopened;
   char *driverName;
   drm_handle_t hFB;
   int junk;
   const __DRIconfig **driver_configs;
   struct glx_config *visual, *configs = NULL, *visuals = NULL;

   /* DRI protocol version. */
   dri_version.major = driDpy->driMajor;
   dri_version.minor = driDpy->driMinor;
   dri_version.patch = driDpy->driPatch;

   framebuffer.base = MAP_FAILED;
   framebuffer.dev_priv = NULL;
   framebuffer.size = 0;

   if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
      ErrorMessageF("XF86DRIOpenConnection failed\n");
      goto handle_error;
   }

   fd = drmOpenOnce(NULL, BusID, &newlyopened);

   free(BusID);                /* No longer needed */

   if (fd < 0) {
      ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
      goto handle_error;
   }

   if (drmGetMagic(fd, &magic)) {
      ErrorMessageF("drmGetMagic failed\n");
      goto handle_error;
   }

   version = drmGetVersion(fd);
   if (version) {
      drm_version.major = version->version_major;
      drm_version.minor = version->version_minor;
      drm_version.patch = version->version_patchlevel;
      drmFreeVersion(version);
   }
   else {
      drm_version.major = -1;
      drm_version.minor = -1;
      drm_version.patch = -1;
   }

   if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
      ErrorMessageF("XF86DRIAuthConnection failed\n");
      goto handle_error;
   }

   /* Get device name (like "radeon") and the ddx version numbers.
    * We'll check the version in each DRI driver's "createNewScreen"
    * function. */
   if (!XF86DRIGetClientDriverName(dpy, scrn,
                                   &ddx_version.major,
                                   &ddx_version.minor,
                                   &ddx_version.patch, &driverName)) {
      ErrorMessageF("XF86DRIGetClientDriverName failed\n");
      goto handle_error;
   }

   free(driverName);           /* No longer needed. */

   /*
    * Get device-specific info.  pDevPriv will point to a struct
    * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
    * has information about the screen size, depth, pitch, ancilliary
    * buffers, DRM mmap handles, etc.
    */
   if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
                             &framebuffer.size, &framebuffer.stride,
                             &framebuffer.dev_priv_size,
                             &framebuffer.dev_priv)) {
      ErrorMessageF("XF86DRIGetDeviceInfo failed\n");
      goto handle_error;
   }

   framebuffer.width = DisplayWidth(dpy, scrn);
   framebuffer.height = DisplayHeight(dpy, scrn);

   /* Map the framebuffer region. */
   status = drmMap(fd, hFB, framebuffer.size,
                   (drmAddressPtr) & framebuffer.base);
   if (status != 0) {
      ErrorMessageF("drmMap of framebuffer failed (%s)\n", strerror(-status));
      goto handle_error;
   }

   /* Map the SAREA region.  Further mmap regions may be setup in
    * each DRI driver's "createNewScreen" function.
    */
   status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
   if (status != 0) {
      ErrorMessageF("drmMap of SAREA failed (%s)\n", strerror(-status));
      goto handle_error;
   }

   psp = (*psc->legacy->createNewScreen) (scrn,
                                          &ddx_version,
                                          &dri_version,
                                          &drm_version,
                                          &framebuffer,
                                          pSAREA,
                                          fd,
                                          loader_extensions,
                                          &driver_configs, psc);

   if (psp == NULL) {
      ErrorMessageF("Calling driver entry point failed\n");
      goto handle_error;
   }

   configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
   visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);

   if (!configs || !visuals)
       goto handle_error;

   glx_config_destroy_list(psc->base.configs);
   psc->base.configs = configs;
   glx_config_destroy_list(psc->base.visuals);
   psc->base.visuals = visuals;

   psc->driver_configs = driver_configs;

   /* Visuals with depth != screen depth are subject to automatic compositing
    * in the X server, so DRI1 can't render to them properly. Mark them as
    * non-conformant to prevent apps from picking them up accidentally.
    */
   for (visual = psc->base.visuals; visual; visual = visual->next) {
      XVisualInfo template;
Example #5
0
static __GLXDRIscreen *
driCreateScreen(__GLXscreenConfigs * psc, int screen,
                __GLXdisplayPrivate * priv)
{
   __GLXDRIscreen *psp;
   const __DRIconfig **driver_configs;
   const __DRIextension **extensions;
   const char *driverName = "swrast";
   int i;

   psp = Xcalloc(1, sizeof *psp);
   if (psp == NULL)
      return NULL;

   psc->driver = driOpenDriver(driverName);
   if (psc->driver == NULL)
      goto handle_error;

   extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
   if (extensions == NULL) {
      ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
      goto handle_error;
   }

   for (i = 0; extensions[i]; i++) {
      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
         psc->core = (__DRIcoreExtension *) extensions[i];
      if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
         psc->swrast = (__DRIswrastExtension *) extensions[i];
   }

   if (psc->core == NULL || psc->swrast == NULL) {
      ErrorMessageF("core dri extension not found\n");
      goto handle_error;
   }

   psc->__driScreen =
      psc->swrast->createNewScreen(screen,
                                   loader_extensions, &driver_configs, psc);
   if (psc->__driScreen == NULL) {
      ErrorMessageF("failed to create dri screen\n");
      goto handle_error;
   }

   driBindExtensions(psc);
   driBindCommonExtensions(psc);

   psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
   psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);

   psc->driver_configs = driver_configs;

   psp->destroyScreen = driDestroyScreen;
   psp->createContext = driCreateContext;
   psp->createDrawable = driCreateDrawable;
   psp->swapBuffers = driSwapBuffers;
   psp->waitX = NULL;
   psp->waitGL = NULL;

   return psp;

 handle_error:
   Xfree(psp);

   if (psc->driver)
      dlclose(psc->driver);

   ErrorMessageF("reverting to indirect rendering\n");

   return NULL;
}
Example #6
0
/**
 * Try to \c dlopen the named driver.
 *
 * This function adds the "_dri.so" suffix to the driver name and searches the
 * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
 * order to find the driver.
 *
 * \param driverName - a name like "i965", "radeon", "nouveau", etc.
 *
 * \returns
 * A handle from \c dlopen, or \c NULL if driver file not found.
 */
_X_HIDDEN void *
driOpenDriver(const char *driverName)
{
   void *glhandle, *handle;
   const char *libPaths, *p, *next;
   char realDriverName[200];
   int len;

   /* Attempt to make sure libGL symbols will be visible to the driver */
   glhandle = dlopen(GL_LIB_NAME, RTLD_NOW | RTLD_GLOBAL);

   libPaths = NULL;
   if (geteuid() == getuid()) {
      /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
      libPaths = getenv("LIBGL_DRIVERS_PATH");
      if (!libPaths)
         libPaths = getenv("LIBGL_DRIVERS_DIR");        /* deprecated */
   }
   if (libPaths == NULL)
      libPaths = DEFAULT_DRIVER_DIR;

   handle = NULL;
   for (p = libPaths; *p; p = next) {
      next = strchr(p, ':');
      if (next == NULL) {
         len = strlen(p);
         next = p + len;
      }
      else {
         len = next - p;
         next++;
      }

#ifdef GLX_USE_TLS
      snprintf(realDriverName, sizeof realDriverName,
               "%.*s/tls/%s_dri.so", len, p, driverName);
      InfoMessageF("OpenDriver: trying %s\n", realDriverName);
      handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
#endif

      if (handle == NULL) {
         snprintf(realDriverName, sizeof realDriverName,
                  "%.*s/%s_dri.so", len, p, driverName);
         InfoMessageF("OpenDriver: trying %s\n", realDriverName);
         handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
      }

      if (handle != NULL)
         break;
      else
         InfoMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
   }

   if (!handle)
      ErrorMessageF("unable to load driver: %s_dri.so\n", driverName);

   if (glhandle)
      dlclose(glhandle);

   return handle;
}
Example #7
0
static __GLXDRIscreen *
dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
                 __GLXdisplayPrivate * priv)
{
    const __DRIconfig **driver_configs;
    const __DRIextension **extensions;
    const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *)
            priv->dri2Display;
    __GLXDRIscreen *psp;
    char *driverName, *deviceName;
    drm_magic_t magic;
    int i;

    psp = Xmalloc(sizeof *psp);
    if (psp == NULL)
        return NULL;

    if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen),
                     &driverName, &deviceName)) {
        XFree(psp);
        return NULL;
    }

    psc->driver = driOpenDriver(driverName);
    if (psc->driver == NULL) {
        ErrorMessageF("driver pointer missing\n");
        goto handle_error;
    }

    extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
    if (extensions == NULL) {
        ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
        goto handle_error;
    }

    for (i = 0; extensions[i]; i++) {
        if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
            psc->core = (__DRIcoreExtension *) extensions[i];
        if (strcmp(extensions[i]->name, __DRI_DRI2) == 0)
            psc->dri2 = (__DRIdri2Extension *) extensions[i];
    }

    if (psc->core == NULL || psc->dri2 == NULL) {
        ErrorMessageF("core dri or dri2 extension not found\n");
        goto handle_error;
    }

    psc->fd = open(deviceName, O_RDWR);
    if (psc->fd < 0) {
        ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
        goto handle_error;
    }

    if (drmGetMagic(psc->fd, &magic)) {
        ErrorMessageF("failed to get magic\n");
        goto handle_error;
    }

    if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) {
        ErrorMessageF("failed to authenticate magic %d\n", magic);
        goto handle_error;
    }

    /* If the server does not support the protocol for
     * DRI2GetBuffersWithFormat, don't supply that interface to the driver.
     */
    psc->__driScreen =
        psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1)
                                   ? loader_extensions_old
                                   : loader_extensions),
                                   &driver_configs, psc);

    if (psc->__driScreen == NULL) {
        ErrorMessageF("failed to create dri screen\n");
        goto handle_error;
    }

    driBindCommonExtensions(psc);
    dri2BindExtensions(psc);

    psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
    psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);

    psc->driver_configs = driver_configs;

    psp->destroyScreen = dri2DestroyScreen;
    psp->createContext = dri2CreateContext;
    psp->createDrawable = dri2CreateDrawable;
    psp->swapBuffers = dri2SwapBuffers;
    psp->waitGL = dri2WaitGL;
    psp->waitX = dri2WaitX;
    psp->getDrawableMSC = NULL;
    psp->waitForMSC = NULL;
    psp->waitForSBC = NULL;
    psp->setSwapInterval = NULL;
    psp->getSwapInterval = NULL;

    if (pdp->driMinor >= 2) {
#ifdef X_DRI2GetMSC
        psp->getDrawableMSC = dri2DrawableGetMSC;
#endif
#ifdef X_DRI2WaitMSC
        psp->waitForMSC = dri2WaitForMSC;
        psp->waitForSBC = dri2WaitForSBC;
#endif
#ifdef X_DRI2SwapInterval
        psp->setSwapInterval = dri2SetSwapInterval;
        psp->getSwapInterval = dri2GetSwapInterval;
#endif
#if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval)
        __glXEnableDirectExtension(psc, "GLX_OML_sync_control");
#endif
    }

    /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
     * available.*/
    psp->copySubBuffer = dri2CopySubBuffer;
    __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");

    Xfree(driverName);
    Xfree(deviceName);

    return psp;

handle_error:
    Xfree(driverName);
    Xfree(deviceName);
    XFree(psp);

    /* FIXME: clean up here */

    return NULL;
}
Example #8
0
/**
 * Try to \c dlopen the named driver.
 *
 * This function adds the "_dri.so" suffix to the driver name and searches the
 * directories specified by the \c LIBGL_DRIVERS_PATH environment variable in
 * order to find the driver.
 *
 * \param driverName - a name like "tdfx", "i810", "mga", etc.
 *
 * \returns
 * A handle from \c dlopen, or \c NULL if driver file not found.
 */
static __DRIdriver *OpenDriver(const char *driverName)
{
   char *libPaths = NULL;
   char libDir[1000];
   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 */
         return driver;
      }
   }

   if (geteuid() == getuid()) {
      /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
      libPaths = getenv("LIBGL_DRIVERS_PATH");
      if (!libPaths)
         libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
   }
   if (!libPaths)
      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.
       */
#ifdef GLX_USE_TLS
      snprintf(realDriverName, 200, "%s/tls/%s_dri.so", libDir, driverName);
      InfoMessageF("OpenDriver: trying %s\n", realDriverName);
      handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
#endif

      if ( handle == NULL ) {
	 snprintf(realDriverName, 200, "%s/%s_dri.so", libDir, driverName);
	 InfoMessageF("OpenDriver: trying %s\n", realDriverName);
	 handle = dlopen(realDriverName, RTLD_NOW | RTLD_GLOBAL);
      }

      if ( handle != NULL ) {
         /* allocate __DRIdriver struct */
         driver = (__DRIdriver *) Xmalloc(sizeof(__DRIdriver));
         if (!driver)
            return NULL; /* out of memory! */
         /* init the struct */
         driver->name = __glXstrdup(driverName);
         if (!driver->name) {
            Xfree(driver);
            return NULL; /* 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);
            dlclose(handle);
            continue;
         }
         driver->handle = handle;
         /* put at head of linked list */
         driver->next = Drivers;
         Drivers = driver;
         return driver;
      }
      else {
	 ErrorMessageF("dlopen %s failed (%s)\n", realDriverName, dlerror());
      }
   }

   ErrorMessageF("unable to find driver: %s_dri.so\n", driverName);
   return NULL;
}