X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fwinsys%2Fsvga%2Fdrm%2Fvmw_fence.c;h=593be9c797b1da7c11f0976c80f8d2254b7b2b94;hb=255de06c5990797832678d7af01876a1afca5b50;hp=edf205e6239c6764a5d2d3578f9940c706b1395e;hpb=628e84a58fdb26c63a705861b92f65f242613321;p=mesa.git diff --git a/src/gallium/winsys/svga/drm/vmw_fence.c b/src/gallium/winsys/svga/drm/vmw_fence.c index edf205e6239..593be9c797b 100644 --- a/src/gallium/winsys/svga/drm/vmw_fence.c +++ b/src/gallium/winsys/svga/drm/vmw_fence.c @@ -22,6 +22,8 @@ * SOFTWARE. * **********************************************************/ +#include + #include "util/u_memory.h" #include "util/u_atomic.h" #include "util/list.h" @@ -32,7 +34,7 @@ #include "vmw_screen.h" #include "vmw_fence.h" -struct vmw_fence_ops +struct vmw_fence_ops { /* * Immutable members. @@ -58,6 +60,8 @@ struct vmw_fence uint32_t mask; int32_t signalled; uint32_t seqno; + int32_t fence_fd; + boolean imported; /* TRUE if imported from another process */ }; /** @@ -175,15 +179,16 @@ vmw_fence(struct pipe_fence_handle *fence) * @fence_ops: The fence_ops manager to register with. * @handle: Handle identifying the kernel fence object. * @mask: Mask of flags that this fence object may signal. + * @fd: File descriptor to associate with the fence * * Returns NULL on failure. */ struct pipe_fence_handle * vmw_fence_create(struct pb_fence_ops *fence_ops, uint32_t handle, - uint32_t seqno, uint32_t mask) + uint32_t seqno, uint32_t mask, int32_t fd) { struct vmw_fence *fence = CALLOC_STRUCT(vmw_fence); - struct vmw_fence_ops *ops = vmw_fence_ops(fence_ops); + struct vmw_fence_ops *ops = NULL; if (!fence) return NULL; @@ -192,15 +197,28 @@ vmw_fence_create(struct pb_fence_ops *fence_ops, uint32_t handle, fence->handle = handle; fence->mask = mask; fence->seqno = seqno; + fence->fence_fd = fd; p_atomic_set(&fence->signalled, 0); + + /* + * If the fence was not created by our device, then we won't + * manage it with our ops + */ + if (!fence_ops) { + fence->imported = true; + return (struct pipe_fence_handle *) fence; + } + + ops = vmw_fence_ops(fence_ops); + mtx_lock(&ops->mutex); if (vmw_fence_seq_is_signaled(seqno, ops->last_signaled, seqno)) { p_atomic_set(&fence->signalled, 1); - LIST_INITHEAD(&fence->ops_list); + list_inithead(&fence->ops_list); } else { p_atomic_set(&fence->signalled, 0); - LIST_ADDTAIL(&fence->ops_list, &ops->not_signaled); + list_addtail(&fence->ops_list, &ops->not_signaled); } mtx_unlock(&ops->mutex); @@ -209,6 +227,21 @@ vmw_fence_create(struct pb_fence_ops *fence_ops, uint32_t handle, } +/** + * vmw_fence_destroy - Frees a vmw fence object. + * + * Also closes the file handle associated with the object, if any + */ +static +void vmw_fence_destroy(struct vmw_fence *vfence) +{ + if (vfence->fence_fd != -1) + close(vfence->fence_fd); + + FREE(vfence); +} + + /** * vmw_fence_reference - Reference / unreference a vmw fence object. * @@ -227,13 +260,15 @@ vmw_fence_reference(struct vmw_winsys_screen *vws, if (p_atomic_dec_zero(&vfence->refcount)) { struct vmw_fence_ops *ops = vmw_fence_ops(vws->fence_ops); - vmw_ioctl_fence_unref(vws, vfence->handle); + if (!vfence->imported) { + vmw_ioctl_fence_unref(vws, vfence->handle); - mtx_lock(&ops->mutex); - LIST_DELINIT(&vfence->ops_list); - mtx_unlock(&ops->mutex); + mtx_lock(&ops->mutex); + LIST_DELINIT(&vfence->ops_list); + mtx_unlock(&ops->mutex); + } - FREE(vfence); + vmw_fence_destroy(vfence); } } @@ -300,6 +335,7 @@ vmw_fence_signalled(struct vmw_winsys_screen *vws, * * @vws: Pointer to the winsys screen. * @fence: Handle to the fence object. + * @timeout: How long to wait before timing out. * @flag: Fence flags to wait for. If the fence object can't signal * a flag, it is assumed to be already signaled. * @@ -308,6 +344,7 @@ vmw_fence_signalled(struct vmw_winsys_screen *vws, int vmw_fence_finish(struct vmw_winsys_screen *vws, struct pipe_fence_handle *fence, + uint64_t timeout, unsigned flag) { struct vmw_fence *vfence; @@ -319,6 +356,16 @@ vmw_fence_finish(struct vmw_winsys_screen *vws, return 0; vfence = vmw_fence(fence); + + if (vfence->imported) { + ret = sync_wait(vfence->fence_fd, timeout / 1000000); + + if (!ret) + p_atomic_set(&vfence->signalled, 1); + + return !!ret; + } + old = p_atomic_read(&vfence->signalled); vflags &= ~vfence->mask; @@ -339,6 +386,23 @@ vmw_fence_finish(struct vmw_winsys_screen *vws, return ret; } +/** + * vmw_fence_get_fd + * + * Returns the file descriptor associated with the fence + */ +int +vmw_fence_get_fd(struct pipe_fence_handle *fence) +{ + struct vmw_fence *vfence; + + if (!fence) + return -1; + + vfence = vmw_fence(fence); + return vfence->fence_fd; +} + /** * vmw_fence_ops_fence_reference - wrapper for the pb_fence_ops api. @@ -383,7 +447,7 @@ vmw_fence_ops_fence_finish(struct pb_fence_ops *ops, { struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws; - return vmw_fence_finish(vws, fence, flag); + return vmw_fence_finish(vws, fence, PIPE_TIMEOUT_INFINITE, flag); } @@ -422,7 +486,7 @@ vmw_fence_ops_create(struct vmw_winsys_screen *vws) return NULL; (void) mtx_init(&ops->mutex, mtx_plain); - LIST_INITHEAD(&ops->not_signaled); + list_inithead(&ops->not_signaled); ops->base.destroy = &vmw_fence_ops_destroy; ops->base.fence_reference = &vmw_fence_ops_fence_reference; ops->base.fence_signalled = &vmw_fence_ops_fence_signalled;