Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
  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.  
  25. #include <string.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <fcntl.h>
  29. #include <errno.h>
  30. #include <kos32sys.h>
  31.  
  32. #include "util/u_memory.h"
  33. #include "egllog.h"
  34.  
  35. #include "native_drm.h"
  36.  
  37. #include "gbm_gallium_drmint.h"
  38.  
  39. #ifdef HAVE_LIBUDEV
  40. #include <libudev.h>
  41. #endif
  42.  
  43. #ifdef HAVE_WAYLAND_BACKEND
  44. #include "common/native_wayland_drm_bufmgr_helper.h"
  45. #endif
  46.  
  47. static boolean
  48. drm_display_is_format_supported(struct native_display *ndpy,
  49.                                 enum pipe_format fmt, boolean is_color)
  50. {
  51.    return ndpy->screen->is_format_supported(ndpy->screen,
  52.          fmt, PIPE_TEXTURE_2D, 0,
  53.          (is_color) ? PIPE_BIND_RENDER_TARGET :
  54.          PIPE_BIND_DEPTH_STENCIL);
  55. }
  56.  
  57. static const struct native_config **
  58. drm_display_get_configs(struct native_display *ndpy, int *num_configs)
  59. {
  60.    struct drm_display *drmdpy = drm_display(ndpy);
  61.    const struct native_config **configs;
  62.  
  63.    /* first time */
  64.    if (!drmdpy->config) {
  65.       struct native_config *nconf;
  66.       enum pipe_format format;
  67.  
  68.       drmdpy->config = CALLOC(1, sizeof(*drmdpy->config));
  69.       if (!drmdpy->config)
  70.          return NULL;
  71.  
  72.       nconf = &drmdpy->config->base;
  73.  
  74.       nconf->buffer_mask =
  75.          (1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
  76.          (1 << NATIVE_ATTACHMENT_BACK_LEFT);
  77.  
  78.       format = PIPE_FORMAT_B8G8R8A8_UNORM;
  79.       if (!drm_display_is_format_supported(&drmdpy->base, format, TRUE)) {
  80.          format = PIPE_FORMAT_A8R8G8B8_UNORM;
  81.          if (!drm_display_is_format_supported(&drmdpy->base, format, TRUE))
  82.             format = PIPE_FORMAT_NONE;
  83.       }
  84.       if (format == PIPE_FORMAT_NONE) {
  85.          FREE(drmdpy->config);
  86.          drmdpy->config = NULL;
  87.          return NULL;
  88.       }
  89.  
  90.       nconf->color_format = format;
  91.  
  92.       /* support KMS */
  93.       if (drmdpy->resources)
  94.          nconf->scanout_bit = TRUE;
  95.    }
  96.  
  97.    configs = MALLOC(sizeof(*configs));
  98.    if (configs) {
  99.       configs[0] = &drmdpy->config->base;
  100.       if (num_configs)
  101.          *num_configs = 1;
  102.    }
  103.  
  104.    return configs;
  105. }
  106.  
  107. static int
  108. drm_display_get_param(struct native_display *ndpy,
  109.                       enum native_param_type param)
  110. {
  111.    int val;
  112.  
  113.    switch (param) {
  114.    case NATIVE_PARAM_USE_NATIVE_BUFFER:
  115.    case NATIVE_PARAM_PRESERVE_BUFFER:
  116.    case NATIVE_PARAM_MAX_SWAP_INTERVAL:
  117.    default:
  118.       val = 0;
  119.       break;
  120.    }
  121.  
  122.    return val;
  123. }
  124.  
  125. static void
  126. drm_display_destroy(struct native_display *ndpy)
  127. {
  128.    struct drm_display *drmdpy = drm_display(ndpy);
  129.  
  130.    FREE(drmdpy->config);
  131.  
  132.    drm_display_fini_modeset(&drmdpy->base);
  133.  
  134.    /* gbm owns screen */
  135.    ndpy->screen = NULL;
  136.    ndpy_uninit(ndpy);
  137.  
  138.    FREE(drmdpy->device_name);
  139.  
  140.    if (drmdpy->own_gbm) {
  141.       gbm_device_destroy(&drmdpy->gbmdrm->base.base);
  142.    }
  143.  
  144.    FREE(drmdpy);
  145. }
  146.  
  147. static struct native_display_buffer drm_display_buffer = {
  148.    /* use the helpers */
  149.    drm_display_import_native_buffer,
  150.    drm_display_export_native_buffer
  151. };
  152.  
  153. static char *
  154. drm_get_device_name(int fd)
  155. {
  156.    char *device_name = NULL;
  157. #ifdef HAVE_LIBUDEV
  158. #endif
  159.    return device_name;
  160. }
  161.  
  162. #ifdef HAVE_WAYLAND_BACKEND
  163.  
  164. static int
  165. drm_display_authenticate(void *user_data, uint32_t magic)
  166. {
  167.    struct native_display *ndpy = user_data;
  168.    struct drm_display *drmdpy = drm_display(ndpy);
  169.  
  170.    return drmAuthMagic(drmdpy->fd, magic);
  171. }
  172.  
  173. static struct wayland_drm_callbacks wl_drm_callbacks = {
  174.    drm_display_authenticate,
  175.    egl_g3d_wl_drm_helper_reference_buffer,
  176.    egl_g3d_wl_drm_helper_unreference_buffer
  177. };
  178.  
  179. static boolean
  180. drm_display_bind_wayland_display(struct native_display *ndpy,
  181.                                   struct wl_display *wl_dpy)
  182. {
  183.    struct drm_display *drmdpy = drm_display(ndpy);
  184.  
  185.    if (ndpy->wl_server_drm)
  186.       return FALSE;
  187.  
  188.    ndpy->wl_server_drm = wayland_drm_init(wl_dpy,
  189.          drmdpy->device_name,
  190.          &wl_drm_callbacks, ndpy, 0);
  191.  
  192.    if (!ndpy->wl_server_drm)
  193.       return FALSE;
  194.  
  195.    return TRUE;
  196. }
  197.  
  198. static boolean
  199. drm_display_unbind_wayland_display(struct native_display *ndpy,
  200.                                     struct wl_display *wl_dpy)
  201. {
  202.    if (!ndpy->wl_server_drm)
  203.       return FALSE;
  204.  
  205.    wayland_drm_uninit(ndpy->wl_server_drm);
  206.    ndpy->wl_server_drm = NULL;
  207.  
  208.    return TRUE;
  209. }
  210.  
  211. static struct native_display_wayland_bufmgr drm_display_wayland_bufmgr = {
  212.    drm_display_bind_wayland_display,
  213.    drm_display_unbind_wayland_display,
  214.    egl_g3d_wl_drm_common_wl_buffer_get_resource,
  215.    egl_g3d_wl_drm_common_query_buffer
  216. };
  217.  
  218. #endif /* HAVE_WAYLAND_BACKEND */
  219.  
  220. static struct native_surface *
  221. drm_create_pixmap_surface(struct native_display *ndpy,
  222.                               EGLNativePixmapType pix,
  223.                               const struct native_config *nconf)
  224. {
  225.    struct gbm_gallium_drm_bo *bo = (void *) pix;
  226.  
  227.    return drm_display_create_surface_from_resource(ndpy, bo->resource);
  228. }
  229.  
  230. static boolean
  231. drm_display_init_screen(struct native_display *ndpy)
  232. {
  233.    return TRUE;
  234. }
  235.  
  236. static struct native_display *
  237. drm_create_display(struct gbm_gallium_drm_device *gbmdrm, int own_gbm,
  238.                    const struct native_event_handler *event_handler)
  239. {
  240.    struct drm_display *drmdpy;
  241.  
  242.    drmdpy = CALLOC_STRUCT(drm_display);
  243.    if (!drmdpy)
  244.       return NULL;
  245.  
  246.    drmdpy->gbmdrm = gbmdrm;
  247.    drmdpy->own_gbm = own_gbm;
  248.    drmdpy->fd = gbmdrm->base.base.fd;
  249.    drmdpy->device_name = drm_get_device_name(drmdpy->fd);
  250.  
  251.    gbmdrm->lookup_egl_image = (struct pipe_resource *(*)(void *, void *))
  252.       event_handler->lookup_egl_image;
  253.    gbmdrm->lookup_egl_image_data = &drmdpy->base;
  254.  
  255.    drmdpy->event_handler = event_handler;
  256.  
  257.    drmdpy->base.screen = gbmdrm->screen;
  258.  
  259.    drmdpy->base.init_screen = drm_display_init_screen;
  260.    drmdpy->base.destroy = drm_display_destroy;
  261.    drmdpy->base.get_param = drm_display_get_param;
  262.    drmdpy->base.get_configs = drm_display_get_configs;
  263.  
  264.    drmdpy->base.create_pixmap_surface = drm_create_pixmap_surface;
  265.  
  266.    drmdpy->base.buffer = &drm_display_buffer;
  267. #ifdef HAVE_WAYLAND_BACKEND
  268.    if (drmdpy->device_name)
  269.       drmdpy->base.wayland_bufmgr = &drm_display_wayland_bufmgr;
  270. #endif
  271.    drm_display_init_modeset(&drmdpy->base);
  272.  
  273.    return &drmdpy->base;
  274. }
  275.  
  276. static const struct native_event_handler *drm_event_handler;
  277.  
  278. static struct native_display *
  279. native_create_display(void *dpy, boolean use_sw)
  280. {
  281.    struct gbm_gallium_drm_device *gbm;
  282.    int fd;
  283.    int own_gbm = 0;
  284.  
  285.    gbm = dpy;
  286.  
  287.    if (gbm == NULL) {
  288.       fd = get_service("DISPLAY");
  289.       if (fd == NULL)
  290.         return NULL;
  291.  
  292.       /* FIXME: Use an internal constructor to create a gbm
  293.        * device with gallium backend directly, without setenv */
  294. //      setenv("GBM_BACKEND", "gbm_gallium_drm.so", 1);
  295.       gbm = gbm_gallium_drm_device(gbm_create_device(fd));
  296.       own_gbm = 1;
  297.    }
  298.  
  299.    if (gbm == NULL)
  300.       return NULL;
  301.  
  302.    if (strcmp(gbm_device_get_backend_name(&gbm->base.base), "drm") != 0 ||
  303.        gbm->base.type != GBM_DRM_DRIVER_TYPE_GALLIUM) {
  304.       if (own_gbm)
  305.          gbm_device_destroy(&gbm->base.base);
  306.       return NULL;
  307.    }
  308.  
  309.    return drm_create_display(gbm, own_gbm, drm_event_handler);
  310. }
  311.  
  312. static const struct native_platform drm_platform = {
  313.    "DRM", /* name */
  314.    native_create_display
  315. };
  316.  
  317. const struct native_platform *
  318. native_get_drm_platform(const struct native_event_handler *event_handler)
  319. {
  320.    drm_event_handler = event_handler;
  321.    return &drm_platform;
  322. }
  323.