summaryrefslogtreecommitdiffstats
path: root/src/gallium/winsys/svga/drm
diff options
context:
space:
mode:
authorThomas Hellstrom <[email protected]>2014-04-07 00:56:42 -0700
committerThomas Hellstrom <[email protected]>2014-04-07 03:34:52 -0700
commit2f6fcd65f2401695427bcbf1f2bd428d466ecda0 (patch)
tree153cf56d39a727597e86674d304afbf7a92e9fce /src/gallium/winsys/svga/drm
parent0887b499e95b0103fa01614cbc9988f0b15c75d6 (diff)
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" <[email protected]> Signed-off-by: Thomas Hellstrom <[email protected]>
Diffstat (limited to 'src/gallium/winsys/svga/drm')
-rw-r--r--src/gallium/winsys/svga/drm/vmw_screen.h4
-rw-r--r--src/gallium/winsys/svga/drm/vmw_screen_dri.c7
-rw-r--r--src/gallium/winsys/svga/drm/vmw_screen_ioctl.c76
3 files changed, 81 insertions, 6 deletions
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"
@@ -251,6 +252,63 @@ out_fail_create:
}
/**
+ * 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;