[Mesa-dev] [PATCH 1/2] loader: refactor duplicated code into loader util lib

Rob Clark robdclark at gmail.com
Sat Dec 14 11:28:32 PST 2013


From: Rob Clark <robclark at freedesktop.org>

All the various window system integration layers duplicate roughly the
same code for figuring out device and driver name, pci-id's, etc.  Which
is sad.  So extract it out into a loader util lib.

Signed-off-by: Rob Clark <robclark at freedesktop.org>
---
 configure.ac                                       |   1 +
 include/pci_ids/pci_id_driver_map.h                |  29 ++-
 src/Makefile.am                                    |   2 +-
 src/egl/drivers/dri2/Makefile.am                   |   5 +-
 src/egl/drivers/dri2/common.c                      | 144 -----------
 src/egl/drivers/dri2/egl_dri2.h                    |   5 -
 src/egl/drivers/dri2/platform_android.c            | 105 +-------
 src/egl/drivers/dri2/platform_drm.c                |   5 +-
 src/egl/drivers/dri2/platform_wayland.c            |   5 +-
 src/gallium/auxiliary/pipe-loader/Makefile.am      |   4 +
 src/gallium/auxiliary/pipe-loader/pipe_loader.h    |   1 +
 .../auxiliary/pipe-loader/pipe_loader_drm.c        |  92 +------
 src/gallium/state_trackers/clover/core/device.cpp  |   2 +
 src/gallium/targets/egl-static/Makefile.am         |   2 +
 src/gallium/targets/egl-static/egl.c               | 186 +--------------
 src/gbm/Makefile.am                                |  10 +-
 src/gbm/backends/dri/driver_name.c                 |  89 -------
 src/gbm/backends/dri/gbm_dri.c                     |   3 +-
 src/gbm/backends/dri/gbm_driint.h                  |   3 -
 src/glx/dri3_common.c                              | 146 ------------
 src/glx/dri3_glx.c                                 |   3 +-
 src/glx/dri3_priv.h                                |   3 -
 src/loader/Makefile.am                             |  37 +++
 src/loader/loader.c                                | 264 +++++++++++++++++++++
 src/loader/loader.h                                |  57 +++++
 25 files changed, 430 insertions(+), 773 deletions(-)
 delete mode 100644 src/egl/drivers/dri2/common.c
 delete mode 100644 src/gbm/backends/dri/driver_name.c
 delete mode 100644 src/glx/dri3_common.c
 create mode 100644 src/loader/Makefile.am
 create mode 100644 src/loader/loader.c
 create mode 100644 src/loader/loader.h

diff --git a/configure.ac b/configure.ac
index c14d39a..8f7e34b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2052,6 +2052,7 @@ AC_CONFIG_FILES([Makefile
 		src/glx/Makefile
 		src/glx/tests/Makefile
 		src/gtest/Makefile
+		src/loader/Makefile
 		src/mapi/Makefile
 		src/mapi/es1api/Makefile
 		src/mapi/es1api/glesv1_cm.pc
diff --git a/include/pci_ids/pci_id_driver_map.h b/include/pci_ids/pci_id_driver_map.h
index 8a97c6f..3ada357 100644
--- a/include/pci_ids/pci_id_driver_map.h
+++ b/include/pci_ids/pci_id_driver_map.h
@@ -3,10 +3,16 @@
 
 #include <stddef.h>
 
+#include "loader.h"
+
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 #endif
 
+#ifndef __IS_LOADER
+#  error "Only include from loader.c"
+#endif
+
 static const int i915_chip_ids[] = {
 #define CHIPSET(chip, desc, name) chip,
 #include "pci_ids/i915_pci_ids.h"
@@ -19,7 +25,6 @@ static const int i965_chip_ids[] = {
 #undef CHIPSET
 };
 
-#ifndef DRIVER_MAP_GALLIUM_ONLY
 static const int r100_chip_ids[] = {
 #define CHIPSET(chip, name, family) chip,
 #include "pci_ids/radeon_pci_ids.h"
@@ -31,7 +36,6 @@ static const int r200_chip_ids[] = {
 #include "pci_ids/r200_pci_ids.h"
 #undef CHIPSET
 };
-#endif
 
 static const int r300_chip_ids[] = {
 #define CHIPSET(chip, name, family) chip,
@@ -62,18 +66,17 @@ static const struct {
    const char *driver;
    const int *chip_ids;
    int num_chips_ids;
+   unsigned driver_types;
 } driver_map[] = {
-   { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) },
-   { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) },
-#ifndef DRIVER_MAP_GALLIUM_ONLY
-   { 0x1002, "radeon", r100_chip_ids, ARRAY_SIZE(r100_chip_ids) },
-   { 0x1002, "r200", r200_chip_ids, ARRAY_SIZE(r200_chip_ids) },
-#endif
-   { 0x1002, "r300", r300_chip_ids, ARRAY_SIZE(r300_chip_ids) },
-   { 0x1002, "r600", r600_chip_ids, ARRAY_SIZE(r600_chip_ids) },
-   { 0x1002, "radeonsi", radeonsi_chip_ids, ARRAY_SIZE(radeonsi_chip_ids) },
-   { 0x10de, "nouveau", NULL, -1 },
-   { 0x15ad, "vmwgfx", vmwgfx_chip_ids, ARRAY_SIZE(vmwgfx_chip_ids) },
+   { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids), _LOADER_DRI | _LOADER_GALLIUM },
+   { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids), _LOADER_DRI | _LOADER_GALLIUM },
+   { 0x1002, "radeon", r100_chip_ids, ARRAY_SIZE(r100_chip_ids), _LOADER_DRI },
+   { 0x1002, "r200", r200_chip_ids, ARRAY_SIZE(r200_chip_ids), _LOADER_DRI },
+   { 0x1002, "r300", r300_chip_ids, ARRAY_SIZE(r300_chip_ids), _LOADER_GALLIUM },
+   { 0x1002, "r600", r600_chip_ids, ARRAY_SIZE(r600_chip_ids), _LOADER_GALLIUM },
+   { 0x1002, "radeonsi", radeonsi_chip_ids, ARRAY_SIZE(radeonsi_chip_ids), _LOADER_GALLIUM},
+   { 0x10de, "nouveau", NULL, -1,  _LOADER_GALLIUM  },
+   { 0x15ad, "vmwgfx", vmwgfx_chip_ids, ARRAY_SIZE(vmwgfx_chip_ids), _LOADER_GALLIUM },
    { 0x0000, NULL, NULL, 0 },
 };
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 76280a0..5b2549d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,7 +19,7 @@
 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 # IN THE SOFTWARE.
 
-SUBDIRS = gtest mapi
+SUBDIRS = gtest loader mapi
 
 if NEED_OPENGL_COMMON
 SUBDIRS += glsl mesa
diff --git a/src/egl/drivers/dri2/Makefile.am b/src/egl/drivers/dri2/Makefile.am
index 823ef5e..6a9ae50 100644
--- a/src/egl/drivers/dri2/Makefile.am
+++ b/src/egl/drivers/dri2/Makefile.am
@@ -22,6 +22,7 @@
 AM_CFLAGS = \
 	-I$(top_srcdir)/include \
 	-I$(top_srcdir)/src/egl/main \
+	-I$(top_srcdir)/src/loader \
 	-I$(top_srcdir)/src/gbm/main \
 	-I$(top_srcdir)/src/gbm/backends/dri \
 	-I$(top_srcdir)/src/egl/wayland/wayland-egl \
@@ -37,10 +38,10 @@ AM_CFLAGS = \
 noinst_LTLIBRARIES = libegl_dri2.la
 
 libegl_dri2_la_SOURCES = \
-	egl_dri2.c \
-	common.c
+	egl_dri2.c
 
 libegl_dri2_la_LIBADD = \
+	$(top_builddir)/src/loader/libloader.la \
 	$(EGL_LIB_DEPS)
 
 if HAVE_SHARED_GLAPI
diff --git a/src/egl/drivers/dri2/common.c b/src/egl/drivers/dri2/common.c
deleted file mode 100644
index a889484..0000000
--- a/src/egl/drivers/dri2/common.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright © 2011 Intel Corporation
- *
- * 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 (including the next
- * paragraph) 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:
- *    Kristian Høgsberg <krh at bitplanet.net>
- *    Benjamin Franzke <benjaminfranzke at googlemail.com>
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "egl_dri2.h"
-
-#ifdef HAVE_LIBUDEV
-
-#define DRIVER_MAP_DRI2_ONLY
-#include "pci_ids/pci_id_driver_map.h"
-
-#include <libudev.h>
-
-static struct udev_device *
-dri2_udev_device_new_from_fd(struct udev *udev, int fd)
-{
-   struct udev_device *device;
-   struct stat buf;
-
-   if (fstat(fd, &buf) < 0) {
-      _eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd);
-      return NULL;
-   }
-
-   device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
-   if (device == NULL) {
-      _eglLog(_EGL_WARNING,
-              "EGL-DRI2: could not create udev device for fd %d", fd);
-      return NULL;
-   }
-
-   return device;
-}
-
-char *
-dri2_get_device_name_for_fd(int fd)
-{
-   struct udev *udev;
-   struct udev_device *device;
-   const char *const_device_name;
-   char *device_name = NULL;
-
-   udev = udev_new();
-   device = dri2_udev_device_new_from_fd(udev, fd);
-   if (device == NULL)
-      return NULL;
-
-   const_device_name = udev_device_get_devnode(device);
-   if (!const_device_name)
-      goto out;
-   device_name = strdup(const_device_name);
-
-out:
-   udev_device_unref(device);
-   udev_unref(udev);
-
-   return device_name;
-}
-
-char *
-dri2_get_driver_for_fd(int fd)
-{
-   struct udev *udev;
-   struct udev_device *device, *parent;
-   const char *pci_id;
-   char *driver = NULL;
-   int vendor_id, chip_id, i, j;
-
-   udev = udev_new();
-   device = dri2_udev_device_new_from_fd(udev, fd);
-   if (device == NULL)
-      return NULL;
-
-   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, "EGL-DRI2: malformed or no PCI ID");
-      goto out;
-   }
-
-   for (i = 0; driver_map[i].driver; i++) {
-      if (vendor_id != driver_map[i].vendor_id)
-         continue;
-      if (driver_map[i].num_chips_ids == -1) {
-         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;
-      }
-
-      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 /* HAVE_LIBUDEV */
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index d29dd98..dfc5927 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -271,9 +271,4 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp);
 EGLBoolean
 dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *disp);
 
-char *
-dri2_get_driver_for_fd(int fd);
-char *
-dri2_get_device_name_for_fd(int fd);
-
 #endif /* EGL_DRI2_INCLUDED */
diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c
index 2c20de7..de147ad 100644
--- a/src/egl/drivers/dri2/platform_android.c
+++ b/src/egl/drivers/dri2/platform_android.c
@@ -34,11 +34,7 @@
 #include <sync/sync.h>
 #endif
 
-/* for droid_get_pci_id */
-#include <xf86drm.h>
-#include <i915_drm.h>
-#include <radeon_drm.h>
-
+#include "loader.h"
 #include "egl_dri2.h"
 #include "gralloc_drm.h"
 
@@ -602,103 +598,6 @@ droid_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
    return (count != 0);
 }
 
-static EGLBoolean
-droid_get_pci_id(int fd, int *vendor_id, int *chip_id)
-{
-   drmVersionPtr version;
-
-   *chip_id = -1;
-
-   version = drmGetVersion(fd);
-   if (!version) {
-      _eglLog(_EGL_WARNING, "invalid drm fd");
-      return EGL_FALSE;
-   }
-   if (!version->name) {
-      _eglLog(_EGL_WARNING, "unable to determine the driver name");
-      drmFreeVersion(version);
-      return EGL_FALSE;
-   }
-
-   if (strcmp(version->name, "i915") == 0) {
-      struct drm_i915_getparam gp;
-      int ret;
-
-      *vendor_id = 0x8086;
-
-      memset(&gp, 0, sizeof(gp));
-      gp.param = I915_PARAM_CHIPSET_ID;
-      gp.value = chip_id;
-      ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
-      if (ret) {
-         _eglLog(_EGL_WARNING, "failed to get param for i915");
-	 *chip_id = -1;
-      }
-   }
-   else if (strcmp(version->name, "radeon") == 0) {
-      struct drm_radeon_info info;
-      int ret;
-
-      *vendor_id = 0x1002;
-
-      memset(&info, 0, sizeof(info));
-      info.request = RADEON_INFO_DEVICE_ID;
-      info.value = (unsigned long) chip_id;
-      ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
-      if (ret) {
-         _eglLog(_EGL_WARNING, "failed to get info for radeon");
-	 *chip_id = -1;
-      }
-   }
-   else if (strcmp(version->name, "nouveau") == 0) {
-      *vendor_id = 0x10de;
-      /* not used */
-      *chip_id = 0;
-   }
-   else if (strcmp(version->name, "vmwgfx") == 0) {
-      *vendor_id = 0x15ad;
-      /* assume SVGA II */
-      *chip_id = 0x0405;
-   }
-
-   drmFreeVersion(version);
-
-   return (*chip_id >= 0);
-}
-
-#define DRIVER_MAP_DRI2_ONLY
-#include "pci_ids/pci_id_driver_map.h"
-static const char *
-droid_get_driver_name(int fd)
-{
-   int vendor_id = -1, chip_id = -1;
-   int idx, i;
-   char *name;
-
-   if (!droid_get_pci_id(fd, &vendor_id, &chip_id))
-      return NULL;
-
-   for (idx = 0; driver_map[idx].driver; idx++) {
-      if (vendor_id != driver_map[idx].vendor_id)
-         continue;
-
-      if (driver_map[idx].num_chips_ids == -1)
-         break;
-
-      for (i = 0; i < driver_map[idx].num_chips_ids; i++) {
-         if (driver_map[idx].chip_ids[i] == chip_id)
-            break;
-      }
-      if (i < driver_map[idx].num_chips_ids)
-	      break;
-   }
-
-   _eglLog(_EGL_INFO, "pci id for fd %d: %04x:%04x, driver %s",
-         fd, vendor_id, chip_id, driver_map[idx].driver);
-
-   return driver_map[idx].driver;
-}
-
 static int
 droid_open_device(void)
 {
@@ -773,7 +672,7 @@ dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy)
       goto cleanup_display;
    }
 
-   dri2_dpy->driver_name = (char *) droid_get_driver_name(dri2_dpy->fd);
+   dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
    if (dri2_dpy->driver_name == NULL) {
       err = "DRI2: failed to get driver name";
       goto cleanup_device;
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index 181b29d..a2b387d 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -36,6 +36,7 @@
 #include <unistd.h>
 
 #include "egl_dri2.h"
+#include "loader.h"
 
 static struct gbm_bo *
 lock_front_buffer(struct gbm_surface *_surf)
@@ -447,6 +448,8 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
    int fd = -1;
    int i;
 
+   loader_set_logger(_eglLog);
+
    dri2_dpy = calloc(1, sizeof *dri2_dpy);
    if (!dri2_dpy)
       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
@@ -482,7 +485,7 @@ dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp)
    }
 
    dri2_dpy->fd = fd;
-   dri2_dpy->device_name = dri2_get_device_name_for_fd(dri2_dpy->fd);
+   dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd);
    dri2_dpy->driver_name = dri2_dpy->gbm_dri->base.driver_name;
 
    dri2_dpy->dri_screen = dri2_dpy->gbm_dri->screen;
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 5c8440d..50750a9 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -36,6 +36,7 @@
 #include <xf86drm.h>
 
 #include "egl_dri2.h"
+#include "loader.h"
 
 #include <wayland-client.h>
 #include "wayland-drm-client-protocol.h"
@@ -962,6 +963,8 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
    static const unsigned int rgb_masks[4] = { 0xff0000, 0xff00, 0xff, 0 };
    static const unsigned int rgb565_masks[4] = { 0xf800, 0x07e0, 0x001f, 0 };
 
+   loader_set_logger(_eglLog);
+
    drv->API.CreateWindowSurface = dri2_create_window_surface;
    drv->API.DestroySurface = dri2_destroy_surface;
    drv->API.SwapBuffers = dri2_swap_buffers;
@@ -1006,7 +1009,7 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
    if (roundtrip(dri2_dpy) < 0 || !dri2_dpy->authenticated)
       goto cleanup_fd;
 
-   dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
+   dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
    if (dri2_dpy->driver_name == NULL) {
       _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
       goto cleanup_fd;
diff --git a/src/gallium/auxiliary/pipe-loader/Makefile.am b/src/gallium/auxiliary/pipe-loader/Makefile.am
index 9a8094f..7e89ea7 100644
--- a/src/gallium/auxiliary/pipe-loader/Makefile.am
+++ b/src/gallium/auxiliary/pipe-loader/Makefile.am
@@ -3,6 +3,7 @@ AUTOMAKE_OPTIONS = subdir-objects
 AM_CPPFLAGS = $(DEFINES) \
 	$(GALLIUM_PIPE_LOADER_DEFINES) \
 	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/src/loader \
 	-I$(top_srcdir)/src/gallium/include \
 	-I$(top_srcdir)/src/gallium/auxiliary \
 	-I$(top_srcdir)/src/gallium/winsys
@@ -12,6 +13,9 @@ noinst_LTLIBRARIES =
 if HAVE_LOADER_GALLIUM
 noinst_LTLIBRARIES += libpipe_loader.la
 
+libpipe_loader_la_LIBADD = \
+	$(top_builddir)/src/loader/libloader.la
+
 libpipe_loader_la_SOURCES = \
 	pipe_loader.h \
 	pipe_loader_priv.h \
diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader.h b/src/gallium/auxiliary/pipe-loader/pipe_loader.h
index 444bdf1..e915c63 100644
--- a/src/gallium/auxiliary/pipe-loader/pipe_loader.h
+++ b/src/gallium/auxiliary/pipe-loader/pipe_loader.h
@@ -44,6 +44,7 @@ struct pipe_screen;
 enum pipe_loader_device_type {
    PIPE_LOADER_DEVICE_SOFTWARE,
    PIPE_LOADER_DEVICE_PCI,
+   PIPE_LOADER_DEVICE_PLATFORM,
    NUM_PIPE_LOADER_DEVICE_TYPES
 };
 
diff --git a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
index 927fb24..fda0ab1 100644
--- a/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
+++ b/src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c
@@ -48,8 +48,7 @@
 #include "util/u_dl.h"
 #include "util/u_debug.h"
 
-#define DRIVER_MAP_GALLIUM_ONLY
-#include "pci_ids/pci_id_driver_map.h"
+#include "loader.h"
 
 struct pipe_loader_drm_device {
    struct pipe_loader_device base;
@@ -59,78 +58,6 @@ struct pipe_loader_drm_device {
 
 #define pipe_loader_drm_device(dev) ((struct pipe_loader_drm_device *)dev)
 
-static boolean
-find_drm_pci_id(struct pipe_loader_drm_device *ddev)
-{
-   struct udev *udev = NULL;
-   struct udev_device *parent, *device = NULL;
-   struct stat stat;
-   const char *pci_id;
-
-   if (fstat(ddev->fd, &stat) < 0)
-      goto fail;
-
-   udev = udev_new();
-   if (!udev)
-      goto fail;
-
-   device = udev_device_new_from_devnum(udev, 'c', stat.st_rdev);
-   if (!device)
-      goto fail;
-
-   parent = udev_device_get_parent(device);
-   if (!parent)
-      goto fail;
-
-   pci_id = udev_device_get_property_value(parent, "PCI_ID");
-   if (!pci_id ||
-       sscanf(pci_id, "%x:%x", &ddev->base.u.pci.vendor_id,
-              &ddev->base.u.pci.chip_id) != 2)
-      goto fail;
-
-   udev_device_unref(device);
-   udev_unref(udev);
-
-   return TRUE;
-
-  fail:
-   if (device)
-      udev_device_unref(device);
-   if (udev)
-      udev_unref(udev);
-
-   return FALSE;
-}
-
-static boolean
-find_drm_driver_name(struct pipe_loader_drm_device *ddev)
-{
-   struct pipe_loader_device *dev = &ddev->base;
-   int i, j;
-
-   for (i = 0; driver_map[i].driver; i++) {
-      if (dev->u.pci.vendor_id != driver_map[i].vendor_id)
-         continue;
-
-      if (driver_map[i].num_chips_ids == -1) {
-         dev->driver_name = driver_map[i].driver;
-         goto found;
-      }
-
-      for (j = 0; j < driver_map[i].num_chips_ids; j++) {
-         if (dev->u.pci.chip_id == driver_map[i].chip_ids[j]) {
-            dev->driver_name = driver_map[i].driver;
-            goto found;
-         }
-      }
-   }
-
-   return FALSE;
-
-  found:
-   return TRUE;
-}
-
 static struct pipe_loader_ops pipe_loader_drm_ops;
 
 static void
@@ -190,17 +117,22 @@ boolean
 pipe_loader_drm_probe_fd(struct pipe_loader_device **dev, int fd)
 {
    struct pipe_loader_drm_device *ddev = CALLOC_STRUCT(pipe_loader_drm_device);
-
-   ddev->base.type = PIPE_LOADER_DEVICE_PCI;
+   int vendor_id, chip_id;
+
+   if (loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id)) {
+      ddev->base.type = PIPE_LOADER_DEVICE_PCI;
+      ddev->base.u.pci.vendor_id = vendor_id;
+      ddev->base.u.pci.chip_id = chip_id;
+   } else {
+      ddev->base.type = PIPE_LOADER_DEVICE_PLATFORM;
+   }
    ddev->base.ops = &pipe_loader_drm_ops;
    ddev->fd = fd;
 
    pipe_loader_drm_x_auth(fd);
 
-   if (!find_drm_pci_id(ddev))
-      goto fail;
-
-   if (!find_drm_driver_name(ddev))
+   ddev->base.driver_name = loader_get_driver_for_fd(fd, _LOADER_GALLIUM);
+   if (!ddev->base.driver_name)
       goto fail;
 
    *dev = &ddev->base;
diff --git a/src/gallium/state_trackers/clover/core/device.cpp b/src/gallium/state_trackers/clover/core/device.cpp
index e5e429a..76a49d0 100644
--- a/src/gallium/state_trackers/clover/core/device.cpp
+++ b/src/gallium/state_trackers/clover/core/device.cpp
@@ -63,6 +63,7 @@ device::type() const {
    case PIPE_LOADER_DEVICE_SOFTWARE:
       return CL_DEVICE_TYPE_CPU;
    case PIPE_LOADER_DEVICE_PCI:
+   case PIPE_LOADER_DEVICE_PLATFORM:
       return CL_DEVICE_TYPE_GPU;
    default:
       assert(0);
@@ -74,6 +75,7 @@ cl_uint
 device::vendor_id() const {
    switch (ldev->type) {
    case PIPE_LOADER_DEVICE_SOFTWARE:
+   case PIPE_LOADER_DEVICE_PLATFORM:
       return 0;
    case PIPE_LOADER_DEVICE_PCI:
       return ldev->u.pci.vendor_id;
diff --git a/src/gallium/targets/egl-static/Makefile.am b/src/gallium/targets/egl-static/Makefile.am
index fdd5a1d..73bb795 100644
--- a/src/gallium/targets/egl-static/Makefile.am
+++ b/src/gallium/targets/egl-static/Makefile.am
@@ -36,6 +36,7 @@ AM_CFLAGS = $(PTHREAD_CFLAGS)
 AM_CPPFLAGS = \
 	$(GALLIUM_CFLAGS) \
 	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/src/loader \
 	-I$(top_srcdir)/src/gallium/drivers \
 	-I$(top_srcdir)/src/gallium/winsys \
 	-I$(top_srcdir)/src/gallium/include \
@@ -60,6 +61,7 @@ egl_gallium_la_LIBADD = \
 	$(top_builddir)/src/gallium/drivers/rbug/librbug.la \
 	$(top_builddir)/src/gallium/state_trackers/egl/libegl.la \
 	$(top_builddir)/src/egl/main/libEGL.la \
+	$(top_builddir)/src/loader/libloader.la \
 	$(CLOCK_LIB) \
 	$(LIBUDEV_LIBS) \
 	$(DLOPEN_LIBS) \
diff --git a/src/gallium/targets/egl-static/egl.c b/src/gallium/targets/egl-static/egl.c
index 0b59bdb..7b515ef 100644
--- a/src/gallium/targets/egl-static/egl.c
+++ b/src/gallium/targets/egl-static/egl.c
@@ -28,14 +28,7 @@
 #include "common/egl_g3d_loader.h"
 #include "egldriver.h"
 #include "egllog.h"
-
-#ifdef HAVE_LIBUDEV
-#include <stdio.h> /* for sscanf */
-#include <libudev.h>
-#endif
-
-#define DRIVER_MAP_GALLIUM_ONLY
-#include "pci_ids/pci_id_driver_map.h"
+#include "loader.h"
 
 #include "egl_pipe.h"
 #include "egl_st.h"
@@ -60,180 +53,14 @@ get_st_api(enum st_api_type api)
    return stmod->stapi;
 }
 
-#ifdef HAVE_LIBUDEV
-
-static boolean
-drm_fd_get_pci_id(int fd, int *vendor_id, int *chip_id)
-{
-   struct udev *udev = NULL;
-   struct udev_device *device = NULL, *parent;
-   struct stat buf;
-   const char *pci_id;
-
-   *chip_id = -1;
-
-   udev = udev_new();
-   if (fstat(fd, &buf) < 0) {
-      _eglLog(_EGL_WARNING, "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,
-              "could not create udev device for fd %d", fd);
-      goto out;
-   }
-
-   parent = udev_device_get_parent(device);
-   if (parent == NULL) {
-      _eglLog(_EGL_WARNING, "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, "malformed or no PCI ID");
-      *chip_id = -1;
-      goto out;
-   }
-
-out:
-   if (device)
-      udev_device_unref(device);
-   if (udev)
-      udev_unref(udev);
-
-   return (*chip_id >= 0);
-}
-
-#elif defined(PIPE_OS_ANDROID) && !defined(_EGL_NO_DRM)
-
-#include <xf86drm.h>
-/* for i915 */
-#include <i915_drm.h>
-/* for radeon */
-#include <radeon_drm.h>
-/* for util_strcmp */
-#include "util/u_string.h"
-
-static boolean
-drm_fd_get_pci_id(int fd, int *vendor_id, int *chip_id)
-{
-   drmVersionPtr version;
-
-   *chip_id = -1;
-
-   version = drmGetVersion(fd);
-   if (!version) {
-      _eglLog(_EGL_WARNING, "invalid drm fd");
-      return FALSE;
-   }
-   if (!version->name) {
-      _eglLog(_EGL_WARNING, "unable to determine the driver name");
-      drmFreeVersion(version);
-      return FALSE;
-   }
-
-   if (util_strcmp(version->name, "i915") == 0) {
-      struct drm_i915_getparam gp;
-      int ret;
-
-      *vendor_id = 0x8086;
-
-      memset(&gp, 0, sizeof(gp));
-      gp.param = I915_PARAM_CHIPSET_ID;
-      gp.value = chip_id;
-      ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
-      if (ret) {
-         _eglLog(_EGL_WARNING, "failed to get param for i915");
-	 *chip_id = -1;
-      }
-   }
-   else if (util_strcmp(version->name, "radeon") == 0) {
-      struct drm_radeon_info info;
-      int ret;
-
-      *vendor_id = 0x1002;
-
-      memset(&info, 0, sizeof(info));
-      info.request = RADEON_INFO_DEVICE_ID;
-      info.value = (unsigned long) chip_id;
-      ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
-      if (ret) {
-         _eglLog(_EGL_WARNING, "failed to get info for radeon");
-	 *chip_id = -1;
-      }
-   }
-   else if (util_strcmp(version->name, "nouveau") == 0) {
-      *vendor_id = 0x10de;
-      /* not used */
-      *chip_id = 0;
-   }
-   else if (util_strcmp(version->name, "vmwgfx") == 0) {
-      *vendor_id = 0x15ad;
-      /* assume SVGA II */
-      *chip_id = 0x0405;
-   }
-
-   drmFreeVersion(version);
-
-   return (*chip_id >= 0);
-}
-
-#else
-
-static boolean
-drm_fd_get_pci_id(int fd, int *vendor_id, int *chip_id)
-{
-   return FALSE;
-}
-
-#endif /* HAVE_LIBUDEV */
-
-static const char *
-drm_fd_get_screen_name(int fd)
-{
-   int vendor_id, chip_id;
-   int idx, i;
-
-   if (!drm_fd_get_pci_id(fd, &vendor_id, &chip_id)) {
-      _eglLog(_EGL_WARNING, "failed to get driver name for fd %d", fd);
-      return NULL;
-   }
-
-   for (idx = 0; driver_map[idx].driver; idx++) {
-      if (vendor_id != driver_map[idx].vendor_id)
-         continue;
-
-      /* done if no chip id */
-      if (driver_map[idx].num_chips_ids == -1)
-         break;
-
-      for (i = 0; i < driver_map[idx].num_chips_ids; i++) {
-         if (driver_map[idx].chip_ids[i] == chip_id)
-            break;
-      }
-      /* matched! */
-      if (i < driver_map[idx].num_chips_ids)
-         break;
-   }
-
-   _eglLog((driver_map[idx].driver) ? _EGL_INFO : _EGL_WARNING,
-         "pci id for fd %d: %04x:%04x, driver %s",
-         fd, vendor_id, chip_id, driver_map[idx].driver);
-
-   return driver_map[idx].driver;
-}
-
 static struct pipe_screen *
-create_drm_screen(const char *name, int fd)
+create_drm_screen(const char *constname, int fd)
 {
    struct pipe_screen *screen;
+   char *name = (char *)constname;
 
    if (!name) {
-      name = drm_fd_get_screen_name(fd);
+      name = loader_get_driver_for_fd(fd, _LOADER_GALLIUM);
       if (!name)
          return NULL;
    }
@@ -244,6 +71,9 @@ create_drm_screen(const char *name, int fd)
    else
       _eglLog(_EGL_WARNING, "failed to create a pipe screen for %s", name);
 
+   if (name != constname)
+      free(name);
+
    return screen;
 }
 
@@ -265,6 +95,8 @@ loader_init(void)
    egl_g3d_loader.create_drm_screen = create_drm_screen;
    egl_g3d_loader.create_sw_screen = create_sw_screen;
 
+   loader_set_logger(_eglLog);
+
    return &egl_g3d_loader;
 }
 
diff --git a/src/gbm/Makefile.am b/src/gbm/Makefile.am
index 9b3fb0d..e7aa706 100644
--- a/src/gbm/Makefile.am
+++ b/src/gbm/Makefile.am
@@ -8,6 +8,7 @@ AM_CFLAGS = \
 	-DMODULEDIR='"$(libdir)/gbm"' \
 	-I$(top_srcdir)/include \
 	-I$(top_srcdir)/src/gbm/main \
+	-I$(top_srcdir)/src/loader \
 	$(LIBUDEV_CFLAGS) \
 	$(LIBKMS_CFLAGS) \
 	$(DLOPEN_CFLAGS) \
@@ -21,7 +22,11 @@ libgbm_la_SOURCES = \
 	main/backend.c \
 	main/common.c
 libgbm_la_LDFLAGS = -version-info 1:0
-libgbm_la_LIBADD = $(LIBUDEV_LIBS) $(LIBKMS_LIBS) $(DLOPEN_LIBS)
+libgbm_la_LIBADD = \
+	$(top_builddir)/src/loader/libloader.la \
+	$(LIBUDEV_LIBS) \
+	$(LIBKMS_LIBS) \
+	$(DLOPEN_LIBS)
 
 if HAVE_EGL_PLATFORM_WAYLAND
 AM_CPPFLAGS = -DHAVE_WAYLAND_PLATFORM
@@ -32,8 +37,7 @@ endif
 if HAVE_DRI
 noinst_LTLIBRARIES = libgbm_dri.la
 libgbm_dri_la_SOURCES = \
-	backends/dri/gbm_dri.c \
-	backends/dri/driver_name.c
+	backends/dri/gbm_dri.c
 
 libgbm_dri_la_CFLAGS = \
 	$(AM_CFLAGS) \
diff --git a/src/gbm/backends/dri/driver_name.c b/src/gbm/backends/dri/driver_name.c
deleted file mode 100644
index 2ed209f..0000000
--- a/src/gbm/backends/dri/driver_name.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright © 2011 Intel Corporation
- *
- * 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 (including the next
- * paragraph) 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:
- *    Kristian Høgsberg <krh at bitplanet.net>
- *    Benjamin Franzke <benjaminfranzke at googlemail.com>
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <libudev.h>
-
-#include "gbm_driint.h"
-#define DRIVER_MAP_DRI2_ONLY
-#include "pci_ids/pci_id_driver_map.h"
-
-char *
-dri_fd_get_driver_name(int fd)
-{
-   struct udev *udev;
-   struct udev_device *device, *parent;
-   const char *pci_id;
-   char *driver = NULL;
-   int vendor_id, chip_id, i, j;
-
-   udev = udev_new();
-   device = _gbm_udev_device_new_from_fd(udev, fd);
-   if (device == NULL)
-      return NULL;
-
-   parent = udev_device_get_parent(device);
-   if (parent == NULL) {
-      fprintf(stderr, "gbm: 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) {
-      fprintf(stderr, "gbm: malformed or no PCI ID");
-      goto out;
-   }
-
-   for (i = 0; driver_map[i].driver; i++) {
-      if (vendor_id != driver_map[i].vendor_id)
-         continue;
-      if (driver_map[i].num_chips_ids == -1) {
-         driver = strdup(driver_map[i].driver);
-         _gbm_log("pci id for %d: %04x:%04x, driver %s",
-                  fd, vendor_id, chip_id, driver);
-         goto out;
-      }
-
-      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);
-            _gbm_log("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;
-}
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
index b4b97ac..c13930c 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -44,6 +44,7 @@
 #include "gbm_driint.h"
 
 #include "gbmint.h"
+#include "loader.h"
 
 /* For importing wl_buffer */
 #if HAVE_WAYLAND_PLATFORM
@@ -270,7 +271,7 @@ dri_screen_create(struct gbm_dri_device *dri)
    const __DRIextension **extensions;
    int ret = 0;
 
-   dri->base.driver_name = dri_fd_get_driver_name(dri->base.base.fd);
+   dri->base.driver_name = loader_get_driver_for_fd(dri->base.base.fd, 0);
    if (dri->base.driver_name == NULL)
       return -1;
 
diff --git a/src/gbm/backends/dri/gbm_driint.h b/src/gbm/backends/dri/gbm_driint.h
index fb303a3..c3a47ab 100644
--- a/src/gbm/backends/dri/gbm_driint.h
+++ b/src/gbm/backends/dri/gbm_driint.h
@@ -111,7 +111,4 @@ gbm_dri_surface(struct gbm_surface *surface)
    return (struct gbm_dri_surface *) surface;
 }
 
-char *
-dri_fd_get_driver_name(int fd);
-
 #endif
diff --git a/src/glx/dri3_common.c b/src/glx/dri3_common.c
deleted file mode 100644
index c758f96..0000000
--- a/src/glx/dri3_common.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright © 2013 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  The copyright holders make no representations
- * about the suitability of this software for any purpose.  It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
-
-/*
- * This code is derived from src/egl/drivers/dri2/common.c which
- * carries the following copyright:
- * 
- * Copyright © 2011 Intel Corporation
- *
- * 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 (including the next
- * paragraph) 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:
- *    Kristian Høgsberg <krh at bitplanet.net>
- *    Benjamin Franzke <benjaminfranzke at googlemail.com>
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <GL/gl.h>
-#include "glapi.h"
-#include "glxclient.h"
-#include "xf86dri.h"
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include "xf86drm.h"
-#include "dri_common.h"
-#include "dri3_priv.h"
-
-#define DRIVER_MAP_DRI3_ONLY
-#include "pci_ids/pci_id_driver_map.h"
-
-#include <libudev.h>
-
-static struct udev_device *
-dri3_udev_device_new_from_fd(struct udev *udev, int fd)
-{
-   struct udev_device *device;
-   struct stat buf;
-
-   if (fstat(fd, &buf) < 0) {
-      ErrorMessageF("DRI3: failed to stat fd %d", fd);
-      return NULL;
-   }
-
-   device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
-   if (device == NULL) {
-      ErrorMessageF("DRI3: could not create udev device for fd %d", fd);
-      return NULL;
-   }
-
-   return device;
-}
-
-char *
-dri3_get_driver_for_fd(int fd)
-{
-   struct udev *udev;
-   struct udev_device *device, *parent;
-   const char *pci_id;
-   char *driver = NULL;
-   int vendor_id, chip_id, i, j;
-
-   udev = udev_new();
-   device = dri3_udev_device_new_from_fd(udev, fd);
-   if (device == NULL)
-      return NULL;
-
-   parent = udev_device_get_parent(device);
-   if (parent == NULL) {
-      ErrorMessageF("DRI3: 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) {
-      ErrorMessageF("DRI3: malformed or no PCI ID");
-      goto out;
-   }
-
-   for (i = 0; driver_map[i].driver; i++) {
-      if (vendor_id != driver_map[i].vendor_id)
-         continue;
-      if (driver_map[i].num_chips_ids == -1) {
-         driver = strdup(driver_map[i].driver);
-         goto out;
-      }
-
-      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);
-            goto out;
-         }
-   }
-
-out:
-   udev_device_unref(device);
-   udev_unref(udev);
-
-   return driver;
-}
diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c
index b047cc8..0e4824b 100644
--- a/src/glx/dri3_glx.c
+++ b/src/glx/dri3_glx.c
@@ -78,6 +78,7 @@
 #include "xf86drm.h"
 #include "dri_common.h"
 #include "dri3_priv.h"
+#include "loader.h"
 
 static const struct glx_context_vtable dri3_context_vtable;
 
@@ -1582,7 +1583,7 @@ dri3_create_screen(int screen, struct glx_display * priv)
    }
    deviceName = NULL;
 
-   driverName = dri3_get_driver_for_fd(psc->fd);
+   driverName = loader_get_driver_for_fd(psc->fd, 0);
    if (!driverName) {
       ErrorMessageF("No driver found\n");
       goto handle_error;
diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h
index c892800..833db29 100644
--- a/src/glx/dri3_priv.h
+++ b/src/glx/dri3_priv.h
@@ -204,6 +204,3 @@ struct dri3_drawable {
    xcb_gcontext_t gc;
    xcb_special_event_t *special_event;
 };
-
-char *
-dri3_get_driver_for_fd(int fd);
diff --git a/src/loader/Makefile.am b/src/loader/Makefile.am
new file mode 100644
index 0000000..dc62164
--- /dev/null
+++ b/src/loader/Makefile.am
@@ -0,0 +1,37 @@
+ # Copyright © 2012 Intel Corporation
+#
+# 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 (including the next
+# paragraph) 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.
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+noinst_LTLIBRARIES = libloader.la
+
+libloader_la_CPPFLAGS = \
+	$(DEFINES) \
+	-I$(top_srcdir)/include \
+	$(LIBDRM_CFLAGS) \
+	$(LIBUDEV_LIBS)
+
+libloader_la_LIBADD = \
+	$(LIBDRM_LIBS) \
+	$(LIBUDEV_LIBS)
+
+libloader_la_SOURCES = loader.c
+
diff --git a/src/loader/loader.c b/src/loader/loader.c
new file mode 100644
index 0000000..3e69a59
--- /dev/null
+++ b/src/loader/loader.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2013 Rob Clark <robclark at freedesktop.org>
+ *
+ * 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 (including the next
+ * paragraph) 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:
+ *    Rob Clark <robclark at freedesktop.org>
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "loader.h"
+
+#include <xf86drm.h>
+
+#define __IS_LOADER
+#include "pci_ids/pci_id_driver_map.h"
+
+static void default_logger(int level, const char *fmt, ...)
+{
+   if (level >= _LOADER_WARNING) {
+      va_list args;
+      va_start(args, fmt);
+      vfprintf(stderr, fmt, args);
+      va_end(args);
+      fprintf(stderr, "\n");
+   }
+}
+
+static void (*log)(int level, const char *fmt, ...) = default_logger;
+
+#ifdef HAVE_LIBUDEV
+#include <libudev.h>
+
+static inline struct udev_device *
+udev_device_new_from_fd(struct udev *udev, int fd)
+{
+   struct udev_device *device;
+   struct stat buf;
+
+   if (fstat(fd, &buf) < 0) {
+      log(_LOADER_WARNING, "EGL-DRI2: failed to stat fd %d", fd);
+      return NULL;
+   }
+
+   device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
+   if (device == NULL) {
+      log(_LOADER_WARNING,
+              "EGL-DRI2: could not create udev device for fd %d", fd);
+      return NULL;
+   }
+
+   return device;
+}
+
+int
+loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id)
+{
+   struct udev *udev = NULL;
+   struct udev_device *device = NULL, *parent;
+   struct stat buf;
+   const char *pci_id;
+
+   *chip_id = -1;
+
+   udev = udev_new();
+   device = udev_device_new_from_fd(udev, fd);
+   if (!device)
+	   goto out;
+
+   parent = udev_device_get_parent(device);
+   if (parent == NULL) {
+      log(_LOADER_WARNING, "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) {
+      log(_LOADER_WARNING, "malformed or no PCI ID");
+      *chip_id = -1;
+      goto out;
+   }
+
+out:
+   if (device)
+      udev_device_unref(device);
+   if (udev)
+      udev_unref(udev);
+
+   return (*chip_id >= 0);
+}
+
+#elif defined(PIPE_OS_ANDROID) && !defined(_EGL_NO_DRM)
+
+/* for i915 */
+#include <i915_drm.h>
+/* for radeon */
+#include <radeon_drm.h>
+
+int
+loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id)
+{
+   drmVersionPtr version;
+
+   *chip_id = -1;
+
+   version = drmGetVersion(fd);
+   if (!version) {
+      log(_LOADER_WARNING, "invalid drm fd");
+      return FALSE;
+   }
+   if (!version->name) {
+      log(_LOADER_WARNING, "unable to determine the driver name");
+      drmFreeVersion(version);
+      return FALSE;
+   }
+
+   if (strcmp(version->name, "i915") == 0) {
+      struct drm_i915_getparam gp;
+      int ret;
+
+      *vendor_id = 0x8086;
+
+      memset(&gp, 0, sizeof(gp));
+      gp.param = I915_PARAM_CHIPSET_ID;
+      gp.value = chip_id;
+      ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
+      if (ret) {
+         log(_LOADER_WARNING, "failed to get param for i915");
+	 *chip_id = -1;
+      }
+   }
+   else if (strcmp(version->name, "radeon") == 0) {
+      struct drm_radeon_info info;
+      int ret;
+
+      *vendor_id = 0x1002;
+
+      memset(&info, 0, sizeof(info));
+      info.request = RADEON_INFO_DEVICE_ID;
+      info.value = (unsigned long) chip_id;
+      ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
+      if (ret) {
+         log(_LOADER_WARNING, "failed to get info for radeon");
+	 *chip_id = -1;
+      }
+   }
+   else if (strcmp(version->name, "nouveau") == 0) {
+      *vendor_id = 0x10de;
+      /* not used */
+      *chip_id = 0;
+   }
+   else if (strcmp(version->name, "vmwgfx") == 0) {
+      *vendor_id = 0x15ad;
+      /* assume SVGA II */
+      *chip_id = 0x0405;
+   }
+
+   drmFreeVersion(version);
+
+   return (*chip_id >= 0);
+}
+
+#else
+
+int
+loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id)
+{
+   return 0;
+}
+
+#endif
+
+
+char *
+loader_get_device_name_for_fd(int fd)
+{
+   char *device_name = NULL;
+#ifdef HAVE_LIBUDEV
+   struct udev *udev;
+   struct udev_device *device;
+   const char *const_device_name;
+
+   udev = udev_new();
+   device = udev_device_new_from_fd(udev, fd);
+   if (device == NULL)
+      return NULL;
+
+   const_device_name = udev_device_get_devnode(device);
+   if (!const_device_name)
+      goto out;
+   device_name = strdup(const_device_name);
+
+out:
+   udev_device_unref(device);
+   udev_unref(udev);
+#endif
+   return device_name;
+}
+
+char *
+loader_get_driver_for_fd(int fd, unsigned driver_types)
+{
+   int vendor_id, chip_id, i, j;
+   char *driver = NULL;
+
+   if (!driver_types)
+      driver_types = _LOADER_GALLIUM | _LOADER_DRI;
+
+   if (!loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id)) {
+      log(_LOADER_WARNING, "failed to get driver name for fd %d", fd);
+      return NULL;
+   }
+
+   for (i = 0; driver_map[i].driver; i++) {
+      if (vendor_id != driver_map[i].vendor_id)
+         continue;
+
+      if (!(driver_types & driver_map[i].driver_types))
+         continue;
+
+      if (driver_map[i].num_chips_ids == -1) {
+         driver = strdup(driver_map[i].driver);
+         goto out;
+      }
+
+      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);
+            goto out;
+         }
+   }
+
+out:
+   log(driver ? _LOADER_INFO : _LOADER_WARNING,
+         "pci id for fd %d: %04x:%04x, driver %s",
+         fd, vendor_id, chip_id, driver);
+   return driver;
+}
+
+void
+loader_set_logger(void (*logger)(int level, const char *fmt, ...))
+{
+   log = logger;
+}
diff --git a/src/loader/loader.h b/src/loader/loader.h
new file mode 100644
index 0000000..dfd77ba
--- /dev/null
+++ b/src/loader/loader.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 Rob Clark <robclark at freedesktop.org>
+ *
+ * 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 (including the next
+ * paragraph) 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:
+ *    Rob Clark <robclark at freedesktop.org>
+ */
+
+#ifndef LOADER_H
+#define LOADER_H
+
+/* Helpers to figure out driver and device name, eg. from pci-id, etc. */
+
+#define _LOADER_DRI          (1 << 0)
+#define _LOADER_GALLIUM      (1 << 1)
+
+int
+loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id);
+
+char *
+loader_get_driver_for_fd(int fd, unsigned driver_types);
+
+char *
+loader_get_device_name_for_fd(int fd);
+
+
+/* for logging.. keep this aligned with egllog.h so we can just use
+ * _eglLog directly.
+ */
+
+#define _LOADER_FATAL   0   /* unrecoverable error */
+#define _LOADER_WARNING 1   /* recoverable error/problem */
+#define _LOADER_INFO    2   /* just useful info */
+#define _LOADER_DEBUG   3   /* useful info for debugging */
+
+void
+loader_set_logger(void (*logger)(int level, const char *fmt, ...));
+
+#endif /* LOADER_H */
-- 
1.8.4.2



More information about the mesa-dev mailing list