[Mesa-dev] [PATCH 3/4] egl_dri2: Support EGL_DISPLAY_TYPE_DRM_MESA

Kristian Høgsberg krh at bitplanet.net
Thu May 27 18:41:46 PDT 2010


This lets the egl_dri2 driver initialize on just a DRM fd.
---
 configs/autoconf.in             |    6 +-
 configure.ac                    |   15 ++++-
 src/egl/drivers/dri2/Makefile   |    6 +-
 src/egl/drivers/dri2/egl_dri2.c |  149 +++++++++++++++++++++++++++++++++++----
 4 files changed, 157 insertions(+), 19 deletions(-)

diff --git a/configs/autoconf.in b/configs/autoconf.in
index 0b5be0c..0238b10 100644
--- a/configs/autoconf.in
+++ b/configs/autoconf.in
@@ -180,8 +180,10 @@ EGL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@
 EGL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@
 EGL_PC_CFLAGS = @GL_PC_CFLAGS@
 
-EGL_DRI2_CFLAGS = @EGL_DRI2_CFLAGS@
-EGL_DRI2_LIBS = @EGL_DRI2_LIBS@
+XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@
+XCB_DRI2_LIBS = @XCB_DRI2_LIBS@
+LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@
+LIBUDEV_LIBS = @LIBUDEV_LIBS@
 
 MESA_LLVM = @MESA_LLVM@
 
diff --git a/configure.ac b/configure.ac
index db4f6d7..532dbf3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1013,11 +1013,22 @@ if test "x$enable_egl" = xyes; then
         fi
 
         # build egl_dri2 when xcb-dri2 is available
-        PKG_CHECK_MODULES([EGL_DRI2], [x11-xcb xcb-dri2 xcb-xfixes libdrm],
+        PKG_CHECK_MODULES([XCB_DRI2], [x11-xcb xcb-dri2 xcb-xfixes],
 			  [have_xcb_dri2=yes],[have_xcb_dri2=no])
+	PKG_CHECK_MODULES([LIBUDEV], [libudev > 150],
+			  [have_libudev=yes],[have_libudev=no])
+
         if test "$have_xcb_dri2" = yes; then
-            EGL_DRIVERS_DIRS="$EGL_DRIVERS_DIRS dri2"
+	    EGL_DRIVER_DRI2=dri2
+            DEFINES="$DEFINES -DHAVE_XCB_DRI2"
+        fi
+
+        if test "$have_libudev" = yes; then
+	    EGL_DRIVER_DRI2=dri2
+            DEFINES="$DEFINES -DHAVE_LIBUDEV"
         fi
+
+        EGL_DRIVERS_DIRS="$EGL_DRIVERS_DIRS $EGL_DRIVER_DRI2"
     fi
 
     if test "$with_demos" = yes; then
diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile
index 4e760ae..8a3c9b6 100644
--- a/src/egl/drivers/dri2/Makefile
+++ b/src/egl/drivers/dri2/Makefile
@@ -11,8 +11,10 @@ EGL_INCLUDES = \
 	-I$(TOP)/src/egl/main \
 	-I$(TOP)/src/mapi \
 	-DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" \
-	$(EGL_DRI2_CFLAGS)
+	$(XCB_DRI2_CFLAGS) \
+	$(LIBUDEV_CFLAGS) \
+	$(LIBDRM_CFLAGS)
 
-EGL_LIBS = $(EGL_DRI2_LIBS)
+EGL_LIBS = $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(LIBDRM_LIBS)
 
 include ../Makefile.template
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 2a775e2..7779cd8 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -40,6 +40,12 @@
 #include <xcb/dri2.h>
 #include <xcb/xfixes.h>
 #include <X11/Xlib-xcb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_LIBUDEV
+#include <libudev.h>
+#endif
 
 #include <glapi/glapi.h>
 #include "eglconfig.h"
@@ -628,6 +634,106 @@ dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
    return EGL_TRUE;
 }
 
+#ifdef HAVE_LIBUDEV
+
+struct dri2_driver_map {
+   int vendor_id;
+   const char *driver;
+   const int *chip_ids;
+   int num_chips_ids;
+};
+
+const int i915_chip_ids[] = {
+   0x3577, /* PCI_CHIP_I830_M */
+   0x2562, /* PCI_CHIP_845_G */
+   0x3582, /* PCI_CHIP_I855_GM */
+   0x2572, /* PCI_CHIP_I865_G */
+   0x2582, /* PCI_CHIP_I915_G */
+   0x258a, /* PCI_CHIP_E7221_G */
+   0x2592, /* PCI_CHIP_I915_GM */
+   0x2772, /* PCI_CHIP_I945_G */
+   0x27a2, /* PCI_CHIP_I945_GM */
+   0x27ae, /* PCI_CHIP_I945_GME */
+   0x29b2, /* PCI_CHIP_Q35_G */
+   0x29c2, /* PCI_CHIP_G33_G */
+   0x29d2, /* PCI_CHIP_Q33_G */
+};
+
+const int i965_chip_ids[] = {
+   0x29a2, /* PCI_CHIP_I965_G */
+   0x2992, /* PCI_CHIP_I965_Q */
+   0x2982, /* PCI_CHIP_I965_G_1 */
+   0x2972, /* PCI_CHIP_I946_GZ */
+   0x2a02, /* PCI_CHIP_I965_GM */
+   0x2a12, /* PCI_CHIP_I965_GME */
+   0x2a42, /* PCI_CHIP_GM45_GM */
+   0x2e02, /* PCI_CHIP_IGD_E_G */
+   0x2e12, /* PCI_CHIP_Q45_G */
+   0x2e22, /* PCI_CHIP_G45_G */
+   0x2e32, /* PCI_CHIP_G41_G */
+};
+
+const struct dri2_driver_map driver_map[] = {
+   { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) },
+   { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) },
+};   
+
+static char *
+dri2_get_driver_for_fd(int fd)
+{
+   struct udev *udev;
+   struct udev_device *device, *parent;
+   struct stat buf;
+   const char *pci_id;
+   char *driver = NULL;
+   int vendor_id, chip_id, i, j;
+
+   udev = udev_new();
+   if (fstat(fd, &buf) < 0) {
+      _eglLog(_EGL_WARNING, "DRI2: failed to stat fd %d", fd);
+      goto out;
+   }
+
+   device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
+   if (device == NULL) {
+      _eglLog(_EGL_WARNING,
+	      "DRI2: could not create udev device for fd %d", fd);
+      goto out;
+   }
+
+   parent = udev_device_get_parent(device);
+   if (parent == NULL) {
+      _eglLog(_EGL_WARNING, "DRI2: could not get parent device");
+      goto out;
+   }
+
+   pci_id = udev_device_get_property_value(parent, "PCI_ID");
+   if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) {
+      _eglLog(_EGL_WARNING, "DRI2: malformed or no PCI ID");
+      goto out;
+   }
+   
+   for (i = 0; i < ARRAY_SIZE(driver_map); i++) {
+      if (vendor_id != driver_map[i].vendor_id)
+	 continue;
+      for (j = 0; j < driver_map[i].num_chips_ids; j++)
+	 if (driver_map[i].chip_ids[j] == chip_id) {
+	    driver = strdup(driver_map[i].driver);
+	    _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s",
+		    fd, vendor_id, chip_id, driver);
+	    goto out;
+	 }
+   }
+
+ out:
+   udev_device_unref(device);
+   udev_unref(udev);
+
+   return driver;
+}
+
+#endif
+
 /**
  * Called via eglInitialize(), GLX_drv->API.Initialize().
  */
@@ -658,6 +764,12 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
       }
       break;
 
+#ifdef HAVE_LIBUDEV
+   case EGL_DISPLAY_TYPE_DRM_MESA:
+      dri2_dpy->fd = (int) disp->VoidDisplay;
+      break;
+#endif
+
    case EGL_DISPLAY_TYPE_XCB_MESA:
       dri2_dpy->conn = disp->VoidDisplay;
       break;
@@ -676,6 +788,22 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
 	 goto cleanup_conn;
    }
 
+   if (dri2_dpy->device_name != NULL) {
+      dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
+      if (dri2_dpy->fd == -1) {
+	 _eglLog(_EGL_WARNING, "DRI2: could not open %s (%s)",
+		 dri2_dpy->device_name, strerror(errno));
+	 goto cleanup_connect;
+      }
+   }
+
+#ifdef HAVE_LIBUDEV
+   if (dri2_dpy->driver_name == NULL)
+      dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
+#endif
+   if (dri2_dpy->driver_name == NULL)
+      goto cleanup_fd;
+
    search_paths = NULL;
    if (geteuid() == getuid()) {
       /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
@@ -711,7 +839,7 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
       _eglLog(_EGL_WARNING,
 	      "DRI2: failed to open any driver (search paths %s)",
 	      search_paths);
-      goto cleanup_conn;
+      goto cleanup_fd;
    }
 
    _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
@@ -725,17 +853,9 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
    if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions))
       goto cleanup_driver;
 
-   dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
-   if (dri2_dpy->fd == -1) {
-      _eglLog(_EGL_WARNING,
-	      "DRI2: could not open %s (%s)", dri2_dpy->device_name,
-              strerror(errno));
-      goto cleanup_driver;
-   }
-
    if (dri2_dpy->conn) {
       if (!dri2_authenticate(dri2_dpy))
-	 goto cleanup_fd;
+	 goto cleanup_driver;
    }
 
    if (dri2_dpy->dri2_minor >= 1) {
@@ -767,7 +887,7 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
 
    if (dri2_dpy->dri_screen == NULL) {
       _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
-      goto cleanup_fd;
+      goto cleanup_driver;
    }
 
    extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
@@ -809,10 +929,13 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
    _eglCleanupDisplay(disp);
  cleanup_dri_screen:
    dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
- cleanup_fd:
-   close(dri2_dpy->fd);
  cleanup_driver:
    dlclose(dri2_dpy->driver);
+ cleanup_fd:
+   close(dri2_dpy->fd);
+ cleanup_connect:
+   free(dri2_dpy->device_name);
+   free(dri2_dpy->driver_name);
  cleanup_conn:
    if (disp->NativeDisplay == NULL)
       xcb_disconnect(dri2_dpy->conn);
-- 
1.7.0.1



More information about the mesa-dev mailing list