Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**********************************************************
  2.  * Copyright 2009 VMware, Inc.  All rights reserved.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person
  5.  * obtaining a copy of this software and associated documentation
  6.  * files (the "Software"), to deal in the Software without
  7.  * restriction, including without limitation the rights to use, copy,
  8.  * modify, merge, publish, distribute, sublicense, and/or sell copies
  9.  * of the Software, and to permit persons to whom the Software is
  10.  * furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice shall be
  13.  * included in all copies or substantial portions of the Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18.  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19.  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20.  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22.  * SOFTWARE.
  23.  *
  24.  **********************************************************/
  25.  
  26.  
  27. #include "pipe/p_compiler.h"
  28. #include "util/u_inlines.h"
  29. #include "util/u_memory.h"
  30. #include "util/u_format.h"
  31.  
  32. #include "vmw_context.h"
  33. #include "vmw_screen.h"
  34. #include "vmw_surface.h"
  35. #include "vmw_buffer.h"
  36. #include "svga_drm_public.h"
  37. #include "svga3d_surfacedefs.h"
  38.  
  39. #include "state_tracker/drm_driver.h"
  40.  
  41. #include "vmwgfx_drm.h"
  42. #include <xf86drm.h>
  43.  
  44. #include <stdio.h>
  45. #include <fcntl.h>
  46.  
  47. struct dri1_api_version {
  48.    int major;
  49.    int minor;
  50.    int patch_level;
  51. };
  52.  
  53. static struct svga_winsys_surface *
  54. vmw_drm_surface_from_handle(struct svga_winsys_screen *sws,
  55.                             struct winsys_handle *whandle,
  56.                             SVGA3dSurfaceFormat *format);
  57.  
  58. static struct svga_winsys_surface *
  59. vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws,
  60.                                struct winsys_handle *whandle,
  61.                                SVGA3dSurfaceFormat *format);
  62. static boolean
  63. vmw_drm_surface_get_handle(struct svga_winsys_screen *sws,
  64.                            struct svga_winsys_surface *surface,
  65.                            unsigned stride,
  66.                            struct winsys_handle *whandle);
  67.  
  68. static struct dri1_api_version drm_required = { 2, 1, 0 };
  69. static struct dri1_api_version drm_compat = { 2, 0, 0 };
  70.  
  71. static boolean
  72. vmw_dri1_check_version(const struct dri1_api_version *cur,
  73.                        const struct dri1_api_version *required,
  74.                        const struct dri1_api_version *compat,
  75.                        const char component[])
  76. {
  77.    if (cur->major > required->major && cur->major <= compat->major)
  78.       return TRUE;
  79.    if (cur->major == required->major && cur->minor >= required->minor)
  80.       return TRUE;
  81.  
  82.    vmw_error("%s version failure.\n", component);
  83.    vmw_error("%s version is %d.%d.%d and this driver can only work\n"
  84.              "with versions %d.%d.x through %d.x.x.\n",
  85.              component,
  86.              cur->major, cur->minor, cur->patch_level,
  87.              required->major, required->minor, compat->major);
  88.    return FALSE;
  89. }
  90.  
  91. /* This is actually the entrypoint to the entire driver,
  92.  * called by the target bootstrap code.
  93.  */
  94. struct svga_winsys_screen *
  95. svga_drm_winsys_screen_create(int fd)
  96. {
  97.    struct vmw_winsys_screen *vws;
  98.    struct dri1_api_version drm_ver;
  99.    drmVersionPtr ver;
  100.  
  101.    ver = drmGetVersion(fd);
  102.    if (ver == NULL)
  103.       return NULL;
  104.  
  105.    drm_ver.major = ver->version_major;
  106.    drm_ver.minor = ver->version_minor;
  107.    drm_ver.patch_level = 0; /* ??? */
  108.  
  109.    drmFreeVersion(ver);
  110.    if (!vmw_dri1_check_version(&drm_ver, &drm_required,
  111.                                &drm_compat, "vmwgfx drm driver"))
  112.       return NULL;
  113.  
  114.    vws = vmw_winsys_create( fd, FALSE );
  115.    if (!vws)
  116.       goto out_no_vws;
  117.  
  118.    /* XXX do this properly */
  119.    vws->base.surface_from_handle = vws->base.have_gb_objects ?
  120.       vmw_drm_gb_surface_from_handle : vmw_drm_surface_from_handle;
  121.    vws->base.surface_get_handle = vmw_drm_surface_get_handle;
  122.  
  123.    return &vws->base;
  124.  
  125. out_no_vws:
  126.    return NULL;
  127. }
  128.  
  129. static INLINE boolean
  130. vmw_dri1_intersect_src_bbox(struct drm_clip_rect *dst,
  131.                             int dst_x,
  132.                             int dst_y,
  133.                             const struct drm_clip_rect *src,
  134.                             const struct drm_clip_rect *bbox)
  135. {
  136.    int xy1;
  137.    int xy2;
  138.  
  139.    xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 :
  140.       (int)bbox->x1 + dst_x;
  141.    xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 :
  142.       (int)bbox->x2 + dst_x;
  143.    if (xy1 >= xy2 || xy1 < 0)
  144.       return FALSE;
  145.  
  146.    dst->x1 = xy1;
  147.    dst->x2 = xy2;
  148.  
  149.    xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 :
  150.       (int)bbox->y1 + dst_y;
  151.    xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 :
  152.       (int)bbox->y2 + dst_y;
  153.    if (xy1 >= xy2 || xy1 < 0)
  154.       return FALSE;
  155.  
  156.    dst->y1 = xy1;
  157.    dst->y2 = xy2;
  158.    return TRUE;
  159. }
  160.  
  161. /**
  162.  * vmw_drm_gb_surface_from_handle - Create a shared surface
  163.  *
  164.  * @sws: Screen to register the surface with.
  165.  * @whandle: struct winsys_handle identifying the kernel surface object
  166.  * @format: On successful return points to a value describing the
  167.  * surface format.
  168.  *
  169.  * Returns a refcounted pointer to a struct svga_winsys_surface
  170.  * embedded in a struct vmw_svga_winsys_surface on success or NULL
  171.  * on failure.
  172.  */
  173. static struct svga_winsys_surface *
  174. vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws,
  175.                                struct winsys_handle *whandle,
  176.                                SVGA3dSurfaceFormat *format)
  177. {
  178.     struct vmw_svga_winsys_surface *vsrf;
  179.     struct svga_winsys_surface *ssrf;
  180.     struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  181.     SVGA3dSurfaceFlags flags;
  182.     uint32_t mip_levels;
  183.     struct vmw_buffer_desc desc;
  184.     struct pb_manager *provider = vws->pools.gmr;
  185.     struct pb_buffer *pb_buf;
  186.     uint32_t handle;
  187.     int ret;
  188.  
  189.     ret = vmw_ioctl_gb_surface_ref(vws, whandle, &flags, format,
  190.                                    &mip_levels, &handle, &desc.region);
  191.  
  192.     if (ret) {
  193.         fprintf(stderr, "Failed referencing shared surface. SID %d.\n"
  194.                 "Error %d (%s).\n",
  195.                 whandle->handle, ret, strerror(-ret));
  196.         return NULL;
  197.     }
  198.  
  199.     if (mip_levels != 1) {
  200.        fprintf(stderr, "Incorrect number of mipmap levels on shared surface."
  201.                " SID %d, levels %d\n",
  202.                whandle->handle, mip_levels);
  203.        goto out_mip;
  204.     }
  205.  
  206.     vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface);
  207.     if (!vsrf)
  208.         goto out_mip;
  209.  
  210.     pipe_reference_init(&vsrf->refcnt, 1);
  211.     p_atomic_set(&vsrf->validated, 0);
  212.     vsrf->screen = vws;
  213.     vsrf->sid = handle;
  214.     vsrf->size = vmw_region_size(desc.region);
  215.  
  216.     /*
  217.      * Synchronize backing buffers of shared surfaces using the
  218.      * kernel, since we don't pass fence objects around between
  219.      * processes.
  220.      */
  221.     desc.pb_desc.alignment = 4096;
  222.     desc.pb_desc.usage = VMW_BUFFER_USAGE_SHARED | VMW_BUFFER_USAGE_SYNC;
  223.     pb_buf = provider->create_buffer(provider, vsrf->size, &desc.pb_desc);
  224.     vsrf->buf = vmw_svga_winsys_buffer_wrap(pb_buf);
  225.     if (!vsrf->buf)
  226.        goto out_no_buf;
  227.     ssrf = svga_winsys_surface(vsrf);
  228.  
  229.     return ssrf;
  230.  
  231. out_no_buf:
  232.     FREE(vsrf);
  233. out_mip:
  234.     vmw_ioctl_region_destroy(desc.region);
  235.     vmw_ioctl_surface_destroy(vws, whandle->handle);
  236.     return NULL;
  237. }
  238.  
  239. static struct svga_winsys_surface *
  240. vmw_drm_surface_from_handle(struct svga_winsys_screen *sws,
  241.                             struct winsys_handle *whandle,
  242.                             SVGA3dSurfaceFormat *format)
  243. {
  244.     struct vmw_svga_winsys_surface *vsrf;
  245.     struct svga_winsys_surface *ssrf;
  246.     struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  247.     union drm_vmw_surface_reference_arg arg;
  248.     struct drm_vmw_surface_arg *req = &arg.req;
  249.     struct drm_vmw_surface_create_req *rep = &arg.rep;
  250.     uint32_t handle = 0;
  251.     struct drm_vmw_size size;
  252.     SVGA3dSize base_size;
  253.     int ret;
  254.     int i;
  255.  
  256.     switch (whandle->type) {
  257.     case DRM_API_HANDLE_TYPE_SHARED:
  258.     case DRM_API_HANDLE_TYPE_KMS:
  259.        handle = whandle->handle;
  260.        break;
  261.     case DRM_API_HANDLE_TYPE_FD:
  262.        ret = drmPrimeFDToHandle(vws->ioctl.drm_fd, whandle->handle,
  263.                                 &handle);
  264.        if (ret) {
  265.           vmw_error("Failed to get handle from prime fd %d.\n",
  266.                     (int) whandle->handle);
  267.           return NULL;
  268.        }
  269.        break;
  270.     default:
  271.        vmw_error("Attempt to import unsupported handle type %d.\n",
  272.                  whandle->type);
  273.        return NULL;
  274.     }
  275.  
  276.     memset(&arg, 0, sizeof(arg));
  277.     req->sid = handle;
  278.     rep->size_addr = (unsigned long)&size;
  279.  
  280.     ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_REF_SURFACE,
  281.                               &arg, sizeof(arg));
  282.  
  283.     /*
  284.      * Need to close the handle we got from prime.
  285.      */
  286.     if (whandle->type == DRM_API_HANDLE_TYPE_FD)
  287.        vmw_ioctl_surface_destroy(vws, handle);
  288.  
  289.     if (ret) {
  290.        /*
  291.         * Any attempt to share something other than a surface, like a dumb
  292.         * kms buffer, should fail here.
  293.         */
  294.        vmw_error("Failed referencing shared surface. SID %d.\n"
  295.                  "Error %d (%s).\n",
  296.                  handle, ret, strerror(-ret));
  297.        return NULL;
  298.     }
  299.  
  300.     if (rep->mip_levels[0] != 1) {
  301.         vmw_error("Incorrect number of mipmap levels on shared surface."
  302.                   " SID %d, levels %d\n",
  303.                   handle, rep->mip_levels[0]);
  304.         goto out_mip;
  305.     }
  306.  
  307.     for (i=1; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
  308.         if (rep->mip_levels[i] != 0) {
  309.             vmw_error("Incorrect number of faces levels on shared surface."
  310.                       " SID %d, face %d present.\n",
  311.                       handle, i);
  312.             goto out_mip;
  313.         }
  314.    }
  315.  
  316.     vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface);
  317.     if (!vsrf)
  318.         goto out_mip;
  319.  
  320.     pipe_reference_init(&vsrf->refcnt, 1);
  321.     p_atomic_set(&vsrf->validated, 0);
  322.     vsrf->screen = vws;
  323.     vsrf->sid = handle;
  324.     ssrf = svga_winsys_surface(vsrf);
  325.     *format = rep->format;
  326.  
  327.     /* Estimate usage, for early flushing. */
  328.  
  329.     base_size.width = size.width;
  330.     base_size.height = size.height;
  331.     base_size.depth = size.depth;
  332.     vsrf->size = svga3dsurface_get_serialized_size(rep->format, base_size,
  333.                                                    rep->mip_levels[0],
  334.                                                    FALSE);
  335.  
  336.     return ssrf;
  337.  
  338. out_mip:
  339.     vmw_ioctl_surface_destroy(vws, handle);
  340.  
  341.     return NULL;
  342. }
  343.  
  344. static boolean
  345. vmw_drm_surface_get_handle(struct svga_winsys_screen *sws,
  346.                            struct svga_winsys_surface *surface,
  347.                            unsigned stride,
  348.                            struct winsys_handle *whandle)
  349. {
  350.     struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  351.     struct vmw_svga_winsys_surface *vsrf;
  352.     int ret;
  353.  
  354.     if (!surface)
  355.         return FALSE;
  356.  
  357.     vsrf = vmw_svga_winsys_surface(surface);
  358.     whandle->handle = vsrf->sid;
  359.     whandle->stride = stride;
  360.  
  361.     switch (whandle->type) {
  362.     case DRM_API_HANDLE_TYPE_SHARED:
  363.     case DRM_API_HANDLE_TYPE_KMS:
  364.        whandle->handle = vsrf->sid;
  365.        break;
  366.     case DRM_API_HANDLE_TYPE_FD:
  367.        ret = drmPrimeHandleToFD(vws->ioctl.drm_fd, vsrf->sid, DRM_CLOEXEC,
  368.                                 (int *)&whandle->handle);
  369.        if (ret) {
  370.           vmw_error("Failed to get file descriptor from prime.\n");
  371.           return FALSE;
  372.        }
  373.        break;
  374.     default:
  375.        vmw_error("Attempt to export unsupported handle type %d.\n",
  376.                  whandle->type);
  377.        return FALSE;
  378.     }
  379.  
  380.     return TRUE;
  381. }
  382.