Example #1
0
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);
         }
      }
   }
}