From 4b74b5b5d16011e5475e8f7c7ac96972243028f5 Mon Sep 17 00:00:00 2001 From: Stanislav Vorobiov Date: Mon, 16 Dec 2013 20:03:38 +0400 Subject: [PATCH] libdrm_vigs: Fence support added VIGS kernel driver now supports fences, so update libdrm to expose them to user space Change-Id: I9c07084a357c0a8dc87c049e01238f9049ca0828 Signed-off-by: Stanislav Vorobiov --- include/drm/vigs_drm.h | 55 ++++++++++++++++--- vigs/Makefile.am | 2 +- vigs/vigs.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++ vigs/vigs.h | 44 ++++++++++++++++ 4 files changed, 233 insertions(+), 7 deletions(-) diff --git a/include/drm/vigs_drm.h b/include/drm/vigs_drm.h index a31053e..3a11ab2 100644 --- a/include/drm/vigs_drm.h +++ b/include/drm/vigs_drm.h @@ -33,7 +33,7 @@ /* * Bump this whenever driver interface changes. */ -#define DRM_VIGS_DRIVER_VERSION 9 +#define DRM_VIGS_DRIVER_VERSION 10 /* * Surface access flags. @@ -71,6 +71,11 @@ struct drm_vigs_gem_map unsigned long address; }; +struct drm_vigs_gem_wait +{ + uint32_t handle; +}; + struct drm_vigs_surface_info { uint32_t handle; @@ -104,15 +109,43 @@ struct drm_vigs_surface_end_access int sync; }; +struct drm_vigs_create_fence +{ + int send; + uint32_t handle; + uint32_t seq; +}; + +struct drm_vigs_fence_wait +{ + uint32_t handle; +}; + +struct drm_vigs_fence_signaled +{ + uint32_t handle; + int signaled; +}; + +struct drm_vigs_fence_unref +{ + uint32_t handle; +}; + #define DRM_VIGS_GET_PROTOCOL_VERSION 0x00 #define DRM_VIGS_CREATE_SURFACE 0x01 #define DRM_VIGS_CREATE_EXECBUFFER 0x02 #define DRM_VIGS_GEM_MAP 0x03 -#define DRM_VIGS_SURFACE_INFO 0x04 -#define DRM_VIGS_EXEC 0x05 -#define DRM_VIGS_SURFACE_SET_GPU_DIRTY 0x06 -#define DRM_VIGS_SURFACE_START_ACCESS 0x07 -#define DRM_VIGS_SURFACE_END_ACCESS 0x08 +#define DRM_VIGS_GEM_WAIT 0x04 +#define DRM_VIGS_SURFACE_INFO 0x05 +#define DRM_VIGS_EXEC 0x06 +#define DRM_VIGS_SURFACE_SET_GPU_DIRTY 0x07 +#define DRM_VIGS_SURFACE_START_ACCESS 0x08 +#define DRM_VIGS_SURFACE_END_ACCESS 0x09 +#define DRM_VIGS_CREATE_FENCE 0x0A +#define DRM_VIGS_FENCE_WAIT 0x0B +#define DRM_VIGS_FENCE_SIGNALED 0x0C +#define DRM_VIGS_FENCE_UNREF 0x0D #define DRM_IOCTL_VIGS_GET_PROTOCOL_VERSION DRM_IOR(DRM_COMMAND_BASE + \ DRM_VIGS_GET_PROTOCOL_VERSION, struct drm_vigs_get_protocol_version) @@ -122,6 +155,8 @@ struct drm_vigs_surface_end_access DRM_VIGS_CREATE_EXECBUFFER, struct drm_vigs_create_execbuffer) #define DRM_IOCTL_VIGS_GEM_MAP DRM_IOWR(DRM_COMMAND_BASE + \ DRM_VIGS_GEM_MAP, struct drm_vigs_gem_map) +#define DRM_IOCTL_VIGS_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + \ + DRM_VIGS_GEM_WAIT, struct drm_vigs_gem_wait) #define DRM_IOCTL_VIGS_SURFACE_INFO DRM_IOWR(DRM_COMMAND_BASE + \ DRM_VIGS_SURFACE_INFO, struct drm_vigs_surface_info) #define DRM_IOCTL_VIGS_EXEC DRM_IOW(DRM_COMMAND_BASE + \ @@ -132,5 +167,13 @@ struct drm_vigs_surface_end_access DRM_VIGS_SURFACE_START_ACCESS, struct drm_vigs_surface_start_access) #define DRM_IOCTL_VIGS_SURFACE_END_ACCESS DRM_IOW(DRM_COMMAND_BASE + \ DRM_VIGS_SURFACE_END_ACCESS, struct drm_vigs_surface_end_access) +#define DRM_IOCTL_VIGS_CREATE_FENCE DRM_IOWR(DRM_COMMAND_BASE + \ + DRM_VIGS_CREATE_FENCE, struct drm_vigs_create_fence) +#define DRM_IOCTL_VIGS_FENCE_WAIT DRM_IOW(DRM_COMMAND_BASE + \ + DRM_VIGS_FENCE_WAIT, struct drm_vigs_fence_wait) +#define DRM_IOCTL_VIGS_FENCE_SIGNALED DRM_IOWR(DRM_COMMAND_BASE + \ + DRM_VIGS_FENCE_SIGNALED, struct drm_vigs_fence_signaled) +#define DRM_IOCTL_VIGS_FENCE_UNREF DRM_IOW(DRM_COMMAND_BASE + \ + DRM_VIGS_FENCE_UNREF, struct drm_vigs_fence_unref) #endif diff --git a/vigs/Makefile.am b/vigs/Makefile.am index dd35bc4..df85b56 100644 --- a/vigs/Makefile.am +++ b/vigs/Makefile.am @@ -12,7 +12,7 @@ AM_CFLAGS = \ libdrm_vigs_la_LTLIBRARIES = libdrm_vigs.la libdrm_vigs_ladir = $(libdir) -libdrm_vigs_la_LDFLAGS = -version-number 4:0:0 -no-undefined +libdrm_vigs_la_LDFLAGS = -version-number 5:0:0 -no-undefined libdrm_vigs_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ libdrm_vigs_la_SOURCES = vigs.c diff --git a/vigs/vigs.c b/vigs/vigs.c index 5530d48..dc95a7c 100644 --- a/vigs/vigs.c +++ b/vigs/vigs.c @@ -73,6 +73,13 @@ struct vigs_drm_execbuffer_impl struct vigs_drm_execbuffer base; }; +struct vigs_drm_fence_impl +{ + struct vigs_drm_fence base; + + atomic_t ref_count; +}; + static void vigs_drm_gem_close(struct vigs_drm_device *dev, uint32_t handle) { struct drm_gem_close req = @@ -257,6 +264,23 @@ void vigs_drm_gem_unmap(struct vigs_drm_gem *gem) gem->vaddr = NULL; } +int vigs_drm_gem_wait(struct vigs_drm_gem *gem) +{ + struct drm_vigs_gem_wait req = + { + .handle = gem->handle, + }; + int ret; + + ret = drmIoctl(gem->dev->fd, DRM_IOCTL_VIGS_GEM_WAIT, &req); + + if (ret != 0) { + return -errno; + } + + return 0; +} + int vigs_drm_surface_create(struct vigs_drm_device *dev, uint32_t width, uint32_t height, @@ -514,3 +538,118 @@ int vigs_drm_execbuffer_exec(struct vigs_drm_execbuffer *execbuffer) return (ret != 0) ? -errno : 0; } + +int vigs_drm_fence_create(struct vigs_drm_device *dev, + int send, + struct vigs_drm_fence **fence) +{ + struct vigs_drm_fence_impl *fence_impl; + struct drm_vigs_create_fence req = + { + .send = send + }; + int ret; + + fence_impl = calloc(sizeof(*fence_impl), 1); + + if (!fence_impl) { + ret = -ENOMEM; + goto fail1; + } + + ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_CREATE_FENCE, &req); + + if (ret != 0) { + ret = -errno; + goto fail2; + } + + atomic_set(&fence_impl->ref_count, 1); + fence_impl->base.dev = dev; + fence_impl->base.handle = req.handle; + fence_impl->base.seq = req.seq; + fence_impl->base.signaled = 0; + + *fence = &fence_impl->base; + + return 0; + +fail2: + free(fence_impl); +fail1: + *fence = NULL; + + return ret; +} + +void vigs_drm_fence_ref(struct vigs_drm_fence *fence) +{ + struct vigs_drm_fence_impl *fence_impl; + + if (!fence) { + return; + } + + fence_impl = vigs_containerof(fence, struct vigs_drm_fence_impl, base); + + atomic_inc(&fence_impl->ref_count); +} + +void vigs_drm_fence_unref(struct vigs_drm_fence *fence) +{ + struct vigs_drm_fence_impl *fence_impl; + struct drm_vigs_fence_unref req; + + if (!fence) { + return; + } + + fence_impl = vigs_containerof(fence, struct vigs_drm_fence_impl, base); + + assert(atomic_read(&fence_impl->ref_count) > 0); + if (!atomic_dec_and_test(&fence_impl->ref_count)) { + return; + } + + req.handle = fence->handle; + + drmIoctl(fence->dev->fd, DRM_IOCTL_VIGS_FENCE_UNREF, &req); + + free(fence_impl); +} + +int vigs_drm_fence_wait(struct vigs_drm_fence *fence) +{ + struct drm_vigs_fence_wait req = + { + .handle = fence->handle + }; + int ret; + + ret = drmIoctl(fence->dev->fd, DRM_IOCTL_VIGS_FENCE_WAIT, &req); + + return (ret != 0) ? -errno : 0; +} + +int vigs_drm_fence_check(struct vigs_drm_fence *fence) +{ + struct drm_vigs_fence_signaled req = + { + .handle = fence->handle + }; + int ret; + + if (fence->signaled) { + return 0; + } + + ret = drmIoctl(fence->dev->fd, DRM_IOCTL_VIGS_FENCE_SIGNALED, &req); + + if (ret != 0) { + return -errno; + } + + fence->signaled = req.signaled; + + return 0; +} diff --git a/vigs/vigs.h b/vigs/vigs.h index 681031a..f44027b 100644 --- a/vigs/vigs.h +++ b/vigs/vigs.h @@ -89,6 +89,21 @@ struct vigs_drm_execbuffer struct vigs_drm_gem gem; }; +struct vigs_drm_fence +{ + /* VIGS device object. */ + struct vigs_drm_device *dev; + + /* a handle to fence object. */ + uint32_t handle; + + /* fence sequence number. */ + uint32_t seq; + + /* is fence signaled ? updated on 'vigs_drm_fence_check'. */ + int signaled; +}; + /* * All functions return 0 on success and < 0 on error, i.e. kernel style: * return -ENOMEM; @@ -134,6 +149,8 @@ int vigs_drm_gem_map(struct vigs_drm_gem *gem, int track_access); void vigs_drm_gem_unmap(struct vigs_drm_gem *gem); +int vigs_drm_gem_wait(struct vigs_drm_gem *gem); + /* * @} */ @@ -185,6 +202,33 @@ int vigs_drm_execbuffer_exec(struct vigs_drm_execbuffer *execbuffer); * @} */ +/* + * Fence functions. + * @{ + */ + +int vigs_drm_fence_create(struct vigs_drm_device *dev, + int send, + struct vigs_drm_fence **fence); + +/* + * Passing NULL won't hurt, this is for convenience. + */ +void vigs_drm_fence_ref(struct vigs_drm_fence *fence); + +/* + * Passing NULL won't hurt, this is for convenience. + */ +void vigs_drm_fence_unref(struct vigs_drm_fence *fence); + +int vigs_drm_fence_wait(struct vigs_drm_fence *fence); + +int vigs_drm_fence_check(struct vigs_drm_fence *fence); + +/* + * @} + */ + #ifdef __cplusplus }; #endif /* __cplusplus */ -- 2.7.4