From 2f6fcd65f2401695427bcbf1f2bd428d466ecda0 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 7 Apr 2014 00:56:42 -0700 Subject: winsys/svga: Fix prime surface references also for guest-backed surfaces Implement guest-backed surface sharing using prime fds. Previously only legacy surfaces could use this functionality. Also use the vmwgfx 2.6 single-ioctl prime fd reference if available. Cc: "10.1" Signed-off-by: Thomas Hellstrom --- src/gallium/winsys/svga/drm/vmw_screen.h | 4 +- src/gallium/winsys/svga/drm/vmw_screen_dri.c | 7 ++- src/gallium/winsys/svga/drm/vmw_screen_ioctl.c | 76 +++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 6 deletions(-) (limited to 'src/gallium/winsys/svga') diff --git a/src/gallium/winsys/svga/drm/vmw_screen.h b/src/gallium/winsys/svga/drm/vmw_screen.h index b68bf431e5e..1a39039aabd 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen.h +++ b/src/gallium/winsys/svga/drm/vmw_screen.h @@ -74,6 +74,7 @@ struct vmw_winsys_screen struct vmw_cap_3d *cap_3d; uint64_t max_mob_memory; uint64_t max_surface_memory; + boolean have_drm_2_6; } ioctl; struct { @@ -138,10 +139,11 @@ vmw_ioctl_gb_surface_create(struct vmw_winsys_screen *vws, int vmw_ioctl_gb_surface_ref(struct vmw_winsys_screen *vws, - uint32_t handle, + const struct winsys_handle *whandle, SVGA3dSurfaceFlags *flags, SVGA3dSurfaceFormat *format, uint32_t *numMipLevels, + uint32_t *handle, struct vmw_region **p_region); void diff --git a/src/gallium/winsys/svga/drm/vmw_screen_dri.c b/src/gallium/winsys/svga/drm/vmw_screen_dri.c index 0f5a9552d85..79a1b3e6dcc 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen_dri.c +++ b/src/gallium/winsys/svga/drm/vmw_screen_dri.c @@ -183,10 +183,11 @@ vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws, struct vmw_buffer_desc desc; struct pb_manager *provider = vws->pools.gmr; struct pb_buffer *pb_buf; + uint32_t handle; int ret; - ret = vmw_ioctl_gb_surface_ref(vws, whandle->handle, &flags, format, - &mip_levels, &desc.region); + ret = vmw_ioctl_gb_surface_ref(vws, whandle, &flags, format, + &mip_levels, &handle, &desc.region); if (ret) { fprintf(stderr, "Failed referencing shared surface. SID %d.\n" @@ -209,7 +210,7 @@ vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws, pipe_reference_init(&vsrf->refcnt, 1); p_atomic_set(&vsrf->validated, 0); vsrf->screen = vws; - vsrf->sid = whandle->handle; + vsrf->sid = handle; vsrf->size = vmw_region_size(desc.region); /* diff --git a/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c b/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c index 2866a29f402..9c0abe96204 100644 --- a/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c +++ b/src/gallium/winsys/svga/drm/vmw_screen_ioctl.c @@ -37,6 +37,7 @@ #include "util/u_memory.h" #include "util/u_math.h" #include "svgadump/svga_dump.h" +#include "state_tracker/drm_driver.h" #include "vmw_screen.h" #include "vmw_context.h" #include "vmw_fence.h" @@ -250,6 +251,63 @@ out_fail_create: return SVGA3D_INVALID_ID; } +/** + * vmw_ioctl_surface_req - Fill in a struct surface_req + * + * @vws: Winsys screen + * @whandle: Surface handle + * @req: The struct surface req to fill in + * @needs_unref: This call takes a kernel surface reference that needs to + * be unreferenced. + * + * Returns 0 on success, negative error type otherwise. + * Fills in the surface_req structure according to handle type and kernel + * capabilities. + */ +static int +vmw_ioctl_surface_req(const struct vmw_winsys_screen *vws, + const struct winsys_handle *whandle, + struct drm_vmw_surface_arg *req, + boolean *needs_unref) +{ + int ret; + + switch(whandle->type) { + case DRM_API_HANDLE_TYPE_SHARED: + case DRM_API_HANDLE_TYPE_KMS: + *needs_unref = FALSE; + req->handle_type = DRM_VMW_HANDLE_LEGACY; + req->sid = whandle->handle; + break; + case DRM_API_HANDLE_TYPE_FD: + if (!vws->ioctl.have_drm_2_6) { + uint32_t handle; + + ret = drmPrimeFDToHandle(vws->ioctl.drm_fd, whandle->handle, &handle); + if (ret) { + vmw_error("Failed to get handle from prime fd %d.\n", + (int) whandle->handle); + return -EINVAL; + } + + *needs_unref = TRUE; + req->handle_type = DRM_VMW_HANDLE_LEGACY; + req->sid = handle; + } else { + *needs_unref = FALSE; + req->handle_type = DRM_VMW_HANDLE_PRIME; + req->sid = whandle->handle; + } + break; + default: + vmw_error("Attempt to import unsupported handle type %d.\n", + whandle->type); + return -EINVAL; + } + + return 0; +} + /** * vmw_ioctl_gb_surface_ref - Put a reference on a guest-backed surface and * get surface information @@ -266,16 +324,18 @@ out_fail_create: */ int vmw_ioctl_gb_surface_ref(struct vmw_winsys_screen *vws, - uint32_t handle, + const struct winsys_handle *whandle, SVGA3dSurfaceFlags *flags, SVGA3dSurfaceFormat *format, uint32_t *numMipLevels, + uint32_t *handle, struct vmw_region **p_region) { union drm_vmw_gb_surface_reference_arg s_arg; struct drm_vmw_surface_arg *req = &s_arg.req; struct drm_vmw_gb_surface_ref_rep *rep = &s_arg.rep; struct vmw_region *region = NULL; + boolean needs_unref = FALSE; int ret; vmw_printf("%s flags %d format %d\n", __FUNCTION__, flags, format); @@ -286,8 +346,11 @@ vmw_ioctl_gb_surface_ref(struct vmw_winsys_screen *vws, return -ENOMEM; memset(&s_arg, 0, sizeof(s_arg)); - req->sid = handle; + ret = vmw_ioctl_surface_req(vws, whandle, req, &needs_unref); + if (ret) + goto out_fail_req; + *handle = req->sid; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GB_SURFACE_REF, &s_arg, sizeof(s_arg)); @@ -300,12 +363,19 @@ vmw_ioctl_gb_surface_ref(struct vmw_winsys_screen *vws, region->size = rep->crep.backup_size; *p_region = region; + *handle = rep->crep.handle; *flags = rep->creq.svga3d_flags; *format = rep->creq.format; *numMipLevels = rep->creq.mip_levels; + if (needs_unref) + vmw_ioctl_surface_destroy(vws, *handle); + return 0; out_fail_ref: + if (needs_unref) + vmw_ioctl_surface_destroy(vws, *handle); +out_fail_req: if (region) FREE(region); return ret; @@ -772,6 +842,8 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws) have_drm_2_5 = version->version_major > 2 || (version->version_major == 2 && version->version_minor > 4); + vws->ioctl.have_drm_2_6 = version->version_major > 2 || + (version->version_major == 2 && version->version_minor > 5); memset(&gp_arg, 0, sizeof(gp_arg)); gp_arg.param = DRM_VMW_PARAM_3D; -- cgit v1.2.3