static int vmw_svga_winsys_fence_finish(struct svga_winsys_screen *sws, struct pipe_fence_handle *fence, unsigned flag) { struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); (void)flag; return vmw_ioctl_fence_finish(vws, vmw_fence(fence)); }
void vmw_ioctl_command(struct vmw_winsys_screen *vws, int32_t cid, uint32_t throttle_us, void *commands, uint32_t size, struct pipe_fence_handle **pfence) { struct drm_vmw_execbuf_arg arg; struct drm_vmw_fence_rep rep; int ret; #ifdef DEBUG { static boolean firsttime = TRUE; static boolean debug = FALSE; static boolean skip = FALSE; if (firsttime) { debug = debug_get_bool_option("SVGA_DUMP_CMD", FALSE); skip = debug_get_bool_option("SVGA_SKIP_CMD", FALSE); } if (debug) { VMW_FUNC; svga_dump_commands(commands, size); } firsttime = FALSE; if (skip) { size = 0; } } #endif memset(&arg, 0, sizeof(arg)); memset(&rep, 0, sizeof(rep)); rep.error = -EFAULT; if (pfence) arg.fence_rep = (unsigned long)&rep; arg.commands = (unsigned long)commands; arg.command_size = size; arg.throttle_us = throttle_us; arg.version = DRM_VMW_EXECBUF_VERSION; do { ret = drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg)); } while(ret == -ERESTART); if (ret) { vmw_error("%s error %s.\n", __FUNCTION__, strerror(-ret)); } if (rep.error) { /* * Kernel has already synced, or caller requested no fence. */ if (pfence) *pfence = NULL; } else { if (pfence) { vmw_fences_signal(vws->fence_ops, rep.passed_seqno, rep.seqno, TRUE); *pfence = vmw_fence_create(vws->fence_ops, rep.handle, rep.seqno, rep.mask); if (*pfence == NULL) { /* * Fence creation failed. Need to sync. */ (void) vmw_ioctl_fence_finish(vws, rep.handle, rep.mask); vmw_ioctl_fence_unref(vws, rep.handle); } } } }
void vmw_ioctl_command(struct vmw_winsys_screen *vws, int32_t cid, uint32_t throttle_us, void *commands, uint32_t size, struct pipe_fence_handle **pfence, int32_t imported_fence_fd, uint32_t flags) { struct drm_vmw_execbuf_arg arg; struct drm_vmw_fence_rep rep; int ret; int argsize; #ifdef DEBUG { static boolean firsttime = TRUE; static boolean debug = FALSE; static boolean skip = FALSE; if (firsttime) { debug = debug_get_bool_option("SVGA_DUMP_CMD", FALSE); skip = debug_get_bool_option("SVGA_SKIP_CMD", FALSE); } if (debug) { VMW_FUNC; svga_dump_commands(commands, size); } firsttime = FALSE; if (skip) { size = 0; } } #endif memset(&arg, 0, sizeof(arg)); memset(&rep, 0, sizeof(rep)); if (flags & SVGA_HINT_FLAG_EXPORT_FENCE_FD) { arg.flags |= DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD; } if (imported_fence_fd != -1) { arg.flags |= DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD; } rep.error = -EFAULT; if (pfence) arg.fence_rep = (unsigned long)&rep; arg.commands = (unsigned long)commands; arg.command_size = size; arg.throttle_us = throttle_us; arg.version = vws->ioctl.drm_execbuf_version; arg.context_handle = (vws->base.have_vgpu10 ? cid : SVGA3D_INVALID_ID); /* Older DRM module requires this to be zero */ if (vws->base.have_fence_fd) arg.imported_fence_fd = imported_fence_fd; /* In DRM_VMW_EXECBUF_VERSION 1, the drm_vmw_execbuf_arg structure ends with * the flags field. The structure size sent to drmCommandWrite must match * the drm_execbuf_version. Otherwise, an invalid value will be returned. */ argsize = vws->ioctl.drm_execbuf_version > 1 ? sizeof(arg) : offsetof(struct drm_vmw_execbuf_arg, context_handle); do { ret = drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_EXECBUF, &arg, argsize); if (ret == -EBUSY) usleep(1000); } while(ret == -ERESTART || ret == -EBUSY); if (ret) { vmw_error("%s error %s.\n", __FUNCTION__, strerror(-ret)); abort(); } if (rep.error) { /* * Kernel has already synced, or caller requested no fence. */ if (pfence) *pfence = NULL; } else { if (pfence) { vmw_fences_signal(vws->fence_ops, rep.passed_seqno, rep.seqno, TRUE); /* Older DRM module will set this to zero, but -1 is the proper FD * to use for no Fence FD support */ if (!vws->base.have_fence_fd) rep.fd = -1; *pfence = vmw_fence_create(vws->fence_ops, rep.handle, rep.seqno, rep.mask, rep.fd); if (*pfence == NULL) { /* * Fence creation failed. Need to sync. */ (void) vmw_ioctl_fence_finish(vws, rep.handle, rep.mask); vmw_ioctl_fence_unref(vws, rep.handle); } } } }