Home | History | Annotate | Download | only in egl-static
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.10
      4  *
      5  * Copyright (C) 2010-2011 LunarG Inc.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     23  * DEALINGS IN THE SOFTWARE.
     24  *
     25  * Authors:
     26  *    Chia-I Wu <olv (at) lunarg.com>
     27  */
     28 
     29 #include "common/egl_g3d_loader.h"
     30 #include "egldriver.h"
     31 #include "egllog.h"
     32 
     33 #ifdef HAVE_LIBUDEV
     34 #include <stdio.h> /* for sscanf */
     35 #include <libudev.h>
     36 #endif
     37 
     38 #define DRIVER_MAP_GALLIUM_ONLY
     39 #include "pci_ids/pci_id_driver_map.h"
     40 
     41 #include "egl_pipe.h"
     42 #include "egl_st.h"
     43 
     44 static struct egl_g3d_loader egl_g3d_loader;
     45 
     46 static struct st_module {
     47    boolean initialized;
     48    struct st_api *stapi;
     49 } st_modules[ST_API_COUNT];
     50 
     51 static struct st_api *
     52 get_st_api(enum st_api_type api)
     53 {
     54    struct st_module *stmod = &st_modules[api];
     55 
     56    if (!stmod->initialized) {
     57       stmod->stapi = egl_st_create_api(api);
     58       stmod->initialized = TRUE;
     59    }
     60 
     61    return stmod->stapi;
     62 }
     63 
     64 #ifdef HAVE_LIBUDEV
     65 
     66 static boolean
     67 drm_fd_get_pci_id(int fd, int *vendor_id, int *chip_id)
     68 {
     69    struct udev *udev = NULL;
     70    struct udev_device *device = NULL, *parent;
     71    struct stat buf;
     72    const char *pci_id;
     73 
     74    *chip_id = -1;
     75 
     76    udev = udev_new();
     77    if (fstat(fd, &buf) < 0) {
     78       _eglLog(_EGL_WARNING, "failed to stat fd %d", fd);
     79       goto out;
     80    }
     81 
     82    device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
     83    if (device == NULL) {
     84       _eglLog(_EGL_WARNING,
     85               "could not create udev device for fd %d", fd);
     86       goto out;
     87    }
     88 
     89    parent = udev_device_get_parent(device);
     90    if (parent == NULL) {
     91       _eglLog(_EGL_WARNING, "could not get parent device");
     92       goto out;
     93    }
     94 
     95    pci_id = udev_device_get_property_value(parent, "PCI_ID");
     96    if (pci_id == NULL ||
     97        sscanf(pci_id, "%x:%x", vendor_id, chip_id) != 2) {
     98       _eglLog(_EGL_WARNING, "malformed or no PCI ID");
     99       *chip_id = -1;
    100       goto out;
    101    }
    102 
    103 out:
    104    if (device)
    105       udev_device_unref(device);
    106    if (udev)
    107       udev_unref(udev);
    108 
    109    return (*chip_id >= 0);
    110 }
    111 
    112 #elif defined(PIPE_OS_ANDROID) && !defined(_EGL_NO_DRM)
    113 
    114 #include <xf86drm.h>
    115 /* for i915 */
    116 #include <i915_drm.h>
    117 /* for radeon */
    118 #include <radeon_drm.h>
    119 /* for util_strcmp */
    120 #include "util/u_string.h"
    121 
    122 static boolean
    123 drm_fd_get_pci_id(int fd, int *vendor_id, int *chip_id)
    124 {
    125    drmVersionPtr version;
    126 
    127    *chip_id = -1;
    128 
    129    version = drmGetVersion(fd);
    130    if (!version) {
    131       _eglLog(_EGL_WARNING, "invalid drm fd");
    132       return FALSE;
    133    }
    134    if (!version->name) {
    135       _eglLog(_EGL_WARNING, "unable to determine the driver name");
    136       drmFreeVersion(version);
    137       return FALSE;
    138    }
    139 
    140    if (util_strcmp(version->name, "i915") == 0) {
    141       struct drm_i915_getparam gp;
    142       int ret;
    143 
    144       *vendor_id = 0x8086;
    145 
    146       memset(&gp, 0, sizeof(gp));
    147       gp.param = I915_PARAM_CHIPSET_ID;
    148       gp.value = chip_id;
    149       ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
    150       if (ret) {
    151          _eglLog(_EGL_WARNING, "failed to get param for i915");
    152 	 *chip_id = -1;
    153       }
    154    }
    155    else if (util_strcmp(version->name, "radeon") == 0) {
    156       struct drm_radeon_info info;
    157       int ret;
    158 
    159       *vendor_id = 0x1002;
    160 
    161       memset(&info, 0, sizeof(info));
    162       info.request = RADEON_INFO_DEVICE_ID;
    163       info.value = (unsigned long) chip_id;
    164       ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
    165       if (ret) {
    166          _eglLog(_EGL_WARNING, "failed to get info for radeon");
    167 	 *chip_id = -1;
    168       }
    169    }
    170    else if (util_strcmp(version->name, "nouveau") == 0) {
    171       *vendor_id = 0x10de;
    172       /* not used */
    173       *chip_id = 0;
    174    }
    175    else if (util_strcmp(version->name, "vmwgfx") == 0) {
    176       *vendor_id = 0x15ad;
    177       /* assume SVGA II */
    178       *chip_id = 0x0405;
    179    }
    180 
    181    drmFreeVersion(version);
    182 
    183    return (*chip_id >= 0);
    184 }
    185 
    186 #else
    187 
    188 static boolean
    189 drm_fd_get_pci_id(int fd, int *vendor_id, int *chip_id)
    190 {
    191    return FALSE;
    192 }
    193 
    194 #endif /* HAVE_LIBUDEV */
    195 
    196 static const char *
    197 drm_fd_get_screen_name(int fd)
    198 {
    199    int vendor_id, chip_id;
    200    int idx, i;
    201 
    202    if (!drm_fd_get_pci_id(fd, &vendor_id, &chip_id)) {
    203       _eglLog(_EGL_WARNING, "failed to get driver name for fd %d", fd);
    204       return NULL;
    205    }
    206 
    207    for (idx = 0; driver_map[idx].driver; idx++) {
    208       if (vendor_id != driver_map[idx].vendor_id)
    209          continue;
    210 
    211       /* done if no chip id */
    212       if (driver_map[idx].num_chips_ids == -1)
    213          break;
    214 
    215       for (i = 0; i < driver_map[idx].num_chips_ids; i++) {
    216          if (driver_map[idx].chip_ids[i] == chip_id)
    217             break;
    218       }
    219       /* matched! */
    220       if (i < driver_map[idx].num_chips_ids)
    221          break;
    222    }
    223 
    224    _eglLog((driver_map[idx].driver) ? _EGL_INFO : _EGL_WARNING,
    225          "pci id for fd %d: %04x:%04x, driver %s",
    226          fd, vendor_id, chip_id, driver_map[idx].driver);
    227 
    228    return driver_map[idx].driver;
    229 }
    230 
    231 static struct pipe_screen *
    232 create_drm_screen(const char *name, int fd)
    233 {
    234    struct pipe_screen *screen;
    235 
    236    if (!name) {
    237       name = drm_fd_get_screen_name(fd);
    238       if (!name)
    239          return NULL;
    240    }
    241 
    242    screen = egl_pipe_create_drm_screen(name, fd);
    243    if (screen)
    244       _eglLog(_EGL_INFO, "created a pipe screen for %s", name);
    245    else
    246       _eglLog(_EGL_WARNING, "failed to create a pipe screen for %s", name);
    247 
    248    return screen;
    249 }
    250 
    251 static struct pipe_screen *
    252 create_sw_screen(struct sw_winsys *ws)
    253 {
    254    return egl_pipe_create_swrast_screen(ws);
    255 }
    256 
    257 static const struct egl_g3d_loader *
    258 loader_init(void)
    259 {
    260    int i;
    261 
    262    for (i = 0; i < ST_API_COUNT; i++)
    263       egl_g3d_loader.profile_masks[i] = egl_st_get_profile_mask(i);
    264 
    265    egl_g3d_loader.get_st_api = get_st_api;
    266    egl_g3d_loader.create_drm_screen = create_drm_screen;
    267    egl_g3d_loader.create_sw_screen = create_sw_screen;
    268 
    269    return &egl_g3d_loader;
    270 }
    271 
    272 static void
    273 loader_fini(void)
    274 {
    275    int i;
    276 
    277    for (i = 0; i < ST_API_COUNT; i++) {
    278       struct st_module *stmod = &st_modules[i];
    279 
    280       if (stmod->stapi) {
    281          egl_st_destroy_api(stmod->stapi);
    282          stmod->stapi = NULL;
    283       }
    284       stmod->initialized = FALSE;
    285    }
    286 }
    287 
    288 static void
    289 egl_g3d_unload(_EGLDriver *drv)
    290 {
    291    egl_g3d_destroy_driver(drv);
    292    loader_fini();
    293 }
    294 
    295 _EGLDriver *
    296 _EGL_MAIN(const char *args)
    297 {
    298    const struct egl_g3d_loader *loader;
    299    _EGLDriver *drv;
    300 
    301    loader = loader_init();
    302    drv = egl_g3d_create_driver(loader);
    303    if (!drv) {
    304       loader_fini();
    305       return NULL;
    306    }
    307 
    308    drv->Name = "Gallium";
    309    drv->Unload = egl_g3d_unload;
    310 
    311    return drv;
    312 }
    313