X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Floader%2Floader.c;h=43275484cc2e0c845e101627ba46e994073fb46c;hp=1eb90e8bba723ce07ad7016cd09f42c9653670fb;hb=9bd8b0f700255611e3eadf91a0f7bb037b6a2e64;hpb=fcdc02f5121823bb37588de507254c926471e28d diff --git a/src/loader/loader.c b/src/loader/loader.c index 1eb90e8bba7..43275484cc2 100644 --- a/src/loader/loader.c +++ b/src/loader/loader.c @@ -1,45 +1,7 @@ /* * Copyright (C) 2013 Rob Clark - * - * This code is derived from the following files. - * - * * src/glx/dri3_common.c - * Copyright © 2013 Keith Packard - * - * * src/egl/drivers/dri2/common.c - * * src/gbm/backends/dri/driver_name.c - * Copyright © 2011 Intel Corporation - * - * Authors: - * Kristian Høgsberg - * Benjamin Franzke - * - * * src/gallium/targets/egl-static/egl.c - * Copyright (C) 2010-2011 LunarG Inc. - * - * Authors: - * Chia-I Wu - * - * * src/gallium/state_trackers/egl/drm/native_drm.c - * Copyright (C) 2010 Chia-I Wu - * - * * src/egl/drivers/dri2/platform_android.c - * - * Copyright (C) 2010-2011 Chia-I Wu - * Copyright (C) 2010-2011 LunarG Inc. - * - * Based on platform_x11, which has - * - * Copyright © 2011 Intel Corporation - * - * * src/gallium/auxiliary/pipe-loader/pipe_loader_drm.c - * Copyright 2011 Intel Corporation - * Copyright 2012 Francisco Jerez - * All Rights Reserved. - * - * Authors: - * Kristian Høgsberg - * Benjamin Franzke + * Copyright (C) 2014-2016 Emil Velikov + * Copyright (C) 2016 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -71,10 +33,8 @@ #include #include #include -#ifdef HAVE_LIBUDEV -#include -#include -#endif +#include +#include #ifdef MAJOR_IN_MKDEV #include #endif @@ -84,12 +44,10 @@ #include "loader.h" #ifdef HAVE_LIBDRM -#include -#include #include #ifdef USE_DRICONF -#include "xmlconfig.h" -#include "xmlpool.h" +#include "util/xmlconfig.h" +#include "util/xmlpool.h" #endif #endif @@ -124,88 +82,6 @@ loader_open_device(const char *device_name) return fd; } -#ifdef HAVE_LIBUDEV -#include - -static void *udev_handle = NULL; - -static void * -udev_dlopen_handle(void) -{ - char name[80]; - unsigned flags = RTLD_NOLOAD | RTLD_LOCAL | RTLD_LAZY; - int version; - - /* libudev.so.1 changed the return types of the two unref functions - * from voids to pointers. We don't use those return values, and the - * only ABI I've heard that cares about this kind of change (calling - * a function with a void * return that actually only returns void) - * might be ia64. - */ - - /* First try opening an already linked libudev, then try loading one */ - do { - for (version = 1; version >= 0; version--) { - snprintf(name, sizeof(name), "libudev.so.%d", version); - udev_handle = dlopen(name, flags); - if (udev_handle) - return udev_handle; - } - - if ((flags & RTLD_NOLOAD) == 0) - break; - - flags &= ~RTLD_NOLOAD; - } while (1); - - log_(_LOADER_WARNING, - "Couldn't dlopen libudev.so.1 or " - "libudev.so.0, driver detection may be broken.\n"); - return NULL; -} - -static int dlsym_failed = 0; - -static void * -checked_dlsym(void *dlopen_handle, const char *name) -{ - void *result = dlsym(dlopen_handle, name); - if (!result) - dlsym_failed = 1; - return result; -} - -#define UDEV_SYMBOL(ret, name, args) \ - ret (*name) args = checked_dlsym(udev_dlopen_handle(), #name); - - -static inline struct udev_device * -udev_device_new_from_fd(struct udev *udev, int fd) -{ - struct udev_device *device; - struct stat buf; - UDEV_SYMBOL(struct udev_device *, udev_device_new_from_devnum, - (struct udev *udev, char type, dev_t devnum)); - - if (dlsym_failed) - return NULL; - - if (fstat(fd, &buf) < 0) { - log_(_LOADER_WARNING, "MESA-LOADER: failed to stat fd %d\n", fd); - return NULL; - } - - device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev); - if (device == NULL) { - log_(_LOADER_WARNING, - "MESA-LOADER: could not create udev device for fd %d\n", fd); - return NULL; - } - - return device; -} -#endif - #if defined(HAVE_LIBDRM) #ifdef USE_DRICONF static const char __driConfigOptionsLoader[] = @@ -234,18 +110,43 @@ static char *loader_get_dri_config_device_id(void) static char *drm_construct_id_path_tag(drmDevicePtr device) { -/* Length of "pci-xxxx_xx_xx_x\0" */ -#define PCI_ID_PATH_TAG_LENGTH 17 char *tag = NULL; if (device->bustype == DRM_BUS_PCI) { - tag = calloc(PCI_ID_PATH_TAG_LENGTH, sizeof(char)); - if (tag == NULL) - return NULL; + if (asprintf(&tag, "pci-%04x_%02x_%02x_%1u", + device->businfo.pci->domain, + device->businfo.pci->bus, + device->businfo.pci->dev, + device->businfo.pci->func) < 0) { + return NULL; + } + } else if (device->bustype == DRM_BUS_PLATFORM || + device->bustype == DRM_BUS_HOST1X) { + char *fullname, *name, *address; + + if (device->bustype == DRM_BUS_PLATFORM) + fullname = device->businfo.platform->fullname; + else + fullname = device->businfo.host1x->fullname; + + name = strrchr(fullname, '/'); + if (!name) + name = strdup(fullname); + else + name = strdup(name + 1); + + address = strchr(name, '@'); + if (address) { + *address++ = '\0'; + + if (asprintf(&tag, "platform-%s_%s", address, name) < 0) + tag = NULL; + } else { + if (asprintf(&tag, "platform-%s", name) < 0) + tag = NULL; + } - snprintf(tag, PCI_ID_PATH_TAG_LENGTH, "pci-%04x_%02x_%02x_%1u", - device->businfo.pci->domain, device->businfo.pci->bus, - device->businfo.pci->dev, device->businfo.pci->func); + free(name); } return tag; } @@ -269,7 +170,7 @@ static char *drm_get_id_path_tag_for_fd(int fd) drmDevicePtr device; char *tag; - if (drmGetDevice(fd, &device) != 0) + if (drmGetDevice2(fd, 0, &device) != 0) return NULL; tag = drm_construct_id_path_tag(device); @@ -277,7 +178,7 @@ static char *drm_get_id_path_tag_for_fd(int fd) return tag; } -int loader_get_user_preferred_fd(int default_fd, int *different_device) +int loader_get_user_preferred_fd(int default_fd, bool *different_device) { /* Arbitrary "maximum" value of drm devices. */ #define MAX_DRM_DEVICES 32 @@ -295,7 +196,7 @@ int loader_get_user_preferred_fd(int default_fd, int *different_device) #endif if (prime == NULL) { - *different_device = 0; + *different_device = false; return default_fd; } @@ -303,7 +204,7 @@ int loader_get_user_preferred_fd(int default_fd, int *different_device) if (default_tag == NULL) goto err; - num_devices = drmGetDevices(devices, MAX_DRM_DEVICES); + num_devices = drmGetDevices2(0, devices, MAX_DRM_DEVICES); if (num_devices < 0) goto err; @@ -354,43 +255,20 @@ int loader_get_user_preferred_fd(int default_fd, int *different_device) return fd; err: - *different_device = 0; + *different_device = false; free(default_tag); free(prime); return default_fd; } #else -int loader_get_user_preferred_fd(int default_fd, int *different_device) +int loader_get_user_preferred_fd(int default_fd, bool *different_device) { - *different_device = 0; + *different_device = false; return default_fd; } #endif -#if defined(HAVE_SYSFS) || defined(HAVE_LIBDRM) -static int -dev_node_from_fd(int fd, unsigned int *maj, unsigned int *min) -{ - struct stat buf; - - if (fstat(fd, &buf) < 0) { - log_(_LOADER_WARNING, "MESA-LOADER: failed to stat fd %d\n", fd); - return -1; - } - - if (!S_ISCHR(buf.st_mode)) { - log_(_LOADER_WARNING, "MESA-LOADER: fd %d not a character device\n", fd); - return -1; - } - - *maj = major(buf.st_rdev); - *min = minor(buf.st_rdev); - - return 0; -} -#endif - #if defined(HAVE_LIBDRM) static int @@ -399,14 +277,14 @@ drm_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) drmDevicePtr device; int ret; - if (drmGetDevice(fd, &device) == 0) { + if (drmGetDevice2(fd, 0, &device) == 0) { if (device->bustype == DRM_BUS_PCI) { *vendor_id = device->deviceinfo.pci->vendor_id; *chip_id = device->deviceinfo.pci->device_id; ret = 1; } else { - log_(_LOADER_WARNING, "MESA-LOADER: device is not located on the PCI bus\n"); + log_(_LOADER_DEBUG, "MESA-LOADER: device is not located on the PCI bus\n"); ret = 0; } drmFreeDevice(&device); @@ -431,131 +309,34 @@ loader_get_pci_id_for_fd(int fd, int *vendor_id, int *chip_id) return 0; } - -#ifdef HAVE_LIBUDEV -static char * -libudev_get_device_name_for_fd(int fd) -{ - char *device_name = NULL; - struct udev *udev; - struct udev_device *device; - const char *const_device_name; - UDEV_SYMBOL(struct udev *, udev_new, (void)); - UDEV_SYMBOL(const char *, udev_device_get_devnode, - (struct udev_device *)); - UDEV_SYMBOL(struct udev_device *, udev_device_unref, - (struct udev_device *)); - UDEV_SYMBOL(struct udev *, udev_unref, (struct udev *)); - - if (dlsym_failed) - return NULL; - - 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); - return device_name; -} -#endif - - -#if HAVE_SYSFS -static char * -sysfs_get_device_name_for_fd(int fd) -{ - char *device_name = NULL; - unsigned int maj, min; - FILE *f; - char buf[0x40]; - static const char match[9] = "\nDEVNAME="; - int expected = 1; - - if (dev_node_from_fd(fd, &maj, &min) < 0) - return NULL; - - snprintf(buf, sizeof(buf), "/sys/dev/char/%d:%d/uevent", maj, min); - if (!(f = fopen(buf, "r"))) - return NULL; - - while (expected < sizeof(match)) { - int c = getc(f); - - if (c == EOF) { - fclose(f); - return NULL; - } else if (c == match[expected] ) - expected++; - else - expected = 0; - } - - strcpy(buf, "/dev/"); - if (fgets(buf + 5, sizeof(buf) - 5, f)) { - buf[strcspn(buf, "\n")] = '\0'; - device_name = strdup(buf); - } - - fclose(f); - return device_name; -} -#endif - -#if defined(HAVE_LIBDRM) -static char * -drm_get_device_name_for_fd(int fd) -{ - unsigned int maj, min; - char buf[0x40]; - int n; - - if (dev_node_from_fd(fd, &maj, &min) < 0) - return NULL; - - n = snprintf(buf, sizeof(buf), DRM_DEV_NAME, DRM_DIR_NAME, min); - if (n == -1 || n >= sizeof(buf)) - return NULL; - - return strdup(buf); -} -#endif - char * loader_get_device_name_for_fd(int fd) { char *result = NULL; -#if HAVE_LIBUDEV - if ((result = libudev_get_device_name_for_fd(fd))) - return result; -#endif -#if HAVE_SYSFS - if ((result = sysfs_get_device_name_for_fd(fd))) - return result; -#endif #if HAVE_LIBDRM - if ((result = drm_get_device_name_for_fd(fd))) - return result; + result = drmGetDeviceNameFromFd2(fd); #endif + return result; } char * -loader_get_driver_for_fd(int fd, unsigned driver_types) +loader_get_driver_for_fd(int fd) { int vendor_id, chip_id, i, j; char *driver = NULL; - if (!driver_types) - driver_types = _LOADER_GALLIUM | _LOADER_DRI; + /* Allow an environment variable to force choosing a different driver + * binary. If that driver binary can't survive on this FD, that's the + * user's problem, but this allows vc4 simulator to run on an i965 host, + * and may be useful for some touch testing of i915 on an i965 host. + */ + if (geteuid() == getuid()) { + driver = getenv("MESA_LOADER_DRIVER_OVERRIDE"); + if (driver) + return strdup(driver); + } if (!loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id)) { @@ -581,9 +362,6 @@ loader_get_driver_for_fd(int fd, unsigned driver_types) if (vendor_id != driver_map[i].vendor_id) continue; - if (!(driver_types & driver_map[i].driver_types)) - continue; - if (driver_map[i].predicate && !driver_map[i].predicate(fd)) continue; @@ -611,3 +389,28 @@ loader_set_logger(void (*logger)(int level, const char *fmt, ...)) { log_ = logger; } + +/* XXX: Local definition to avoid pulling the heavyweight GL/gl.h and + * GL/internal/dri_interface.h + */ + +#ifndef __DRI_DRIVER_GET_EXTENSIONS +#define __DRI_DRIVER_GET_EXTENSIONS "__driDriverGetExtensions" +#endif + +char * +loader_get_extensions_name(const char *driver_name) +{ + char *name = NULL; + + if (asprintf(&name, "%s_%s", __DRI_DRIVER_GET_EXTENSIONS, driver_name) < 0) + return NULL; + + const size_t len = strlen(name); + for (size_t i = 0; i < len; i++) { + if (name[i] == '-') + name[i] = '_'; + } + + return name; +}