Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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