int vrend_renderer_copy_transfer3d_from_host(struct vrend_context *ctx,
                                   uint32_t dst_handle,
                                   uint32_t src_handle,
                                   const struct vrend_transfer_info *info)
{
   struct vrend_resource *src_res, *dst_res;

   src_res = vrend_renderer_ctx_res_lookup(ctx, src_handle);
   dst_res = vrend_renderer_ctx_res_lookup(ctx, dst_handle);

   if (!src_res) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, src_handle);
      return EINVAL;
   }

   if (!dst_res) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, dst_handle);
      return EINVAL;
   }

   if (!dst_res->iov) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, dst_handle);
      return EINVAL;
   }

   if (!check_transfer_bounds(src_res, info)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, dst_handle);
      return EINVAL;
   }

   if (!check_iov_bounds(src_res, info, dst_res->iov, dst_res->num_iovs)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, dst_handle);
      return EINVAL;
   }

   return vrend_renderer_transfer_send_iov(ctx, src_res, dst_res->iov,
                                           dst_res->num_iovs, info);
}
int vrend_renderer_copy_transfer3d_from_host(struct vrend_context *ctx,
                                   uint32_t dst_handle,
                                   uint32_t src_handle,
                                   const struct vrend_transfer_info *info)
{
   struct vrend_resource *src_res, *dst_res;

   src_res = vrend_renderer_ctx_res_lookup(ctx, src_handle);
   dst_res = vrend_renderer_ctx_res_lookup(ctx, dst_handle);

   if (!src_res) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, src_handle);
      return EINVAL;
   }

   if (!dst_res) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, dst_handle);
      return EINVAL;
   }

   if (!dst_res->iov) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, dst_handle);
      return EINVAL;
   }

   if (!check_transfer_bounds(src_res, info)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, dst_handle);
      return EINVAL;
   }

   if (!check_iov_bounds(src_res, info, dst_res->iov, dst_res->num_iovs)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, dst_handle);
      return EINVAL;
   }

   return vrend_renderer_transfer_send_iov(ctx, src_res, dst_res->iov,
                                           dst_res->num_iovs, info);
}