static int vrend_renderer_transfer_internal(struct vrend_context *ctx,
                                            struct vrend_resource *res,
                                            const struct vrend_transfer_info *info,
                                            int transfer_mode)
{
   const struct iovec *iov;
   int num_iovs;

   if (!info->box)
      return EINVAL;

   vrend_hw_switch_context(ctx, true);

   assert(check_transfer_iovec(res, info));
   if (info->iovec && info->iovec_cnt) {
      iov = info->iovec;
      num_iovs = info->iovec_cnt;
   } else {
      iov = res->iov;
      num_iovs = res->num_iovs;
   }

#ifdef ENABLE_MINIGBM_ALLOCATION
   if (res->gbm_bo && (transfer_mode == VIRGL_TRANSFER_TO_HOST ||
                       !has_bit(res->storage_bits, VREND_STORAGE_EGL_IMAGE))) {
      assert(!info->synchronized);
      return virgl_gbm_transfer(res->gbm_bo, transfer_mode, iov, num_iovs, info);
   }
#endif

   if (!check_transfer_bounds(res, info)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_TRANSFER_IOV_BOUNDS, res->id);
      return EINVAL;
   }

   if (!check_iov_bounds(res, info, iov, num_iovs)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_TRANSFER_IOV_BOUNDS, res->id);
      return EINVAL;
   }

   switch (transfer_mode) {
   case VIRGL_TRANSFER_TO_HOST:
      return vrend_renderer_transfer_write_iov(ctx, res, iov, num_iovs, info);
   case VIRGL_TRANSFER_FROM_HOST:
      return vrend_renderer_transfer_send_iov(ctx, res, iov, num_iovs, info);

   default:
      assert(0);
   }
   return 0;
}
static int vrend_renderer_transfer_internal(struct vrend_context *ctx,
                                            struct vrend_resource *res,
                                            const struct vrend_transfer_info *info,
                                            int transfer_mode)
{
   const struct iovec *iov;
   int num_iovs;

   if (!info->box)
      return EINVAL;

   vrend_hw_switch_context(ctx, true);

   assert(check_transfer_iovec(res, info));
   if (info->iovec && info->iovec_cnt) {
      iov = info->iovec;
      num_iovs = info->iovec_cnt;
   } else {
      iov = res->iov;
      num_iovs = res->num_iovs;
   }

#ifdef ENABLE_MINIGBM_ALLOCATION
   if (res->gbm_bo && (transfer_mode == VIRGL_TRANSFER_TO_HOST ||
                       !has_bit(res->storage_bits, VREND_STORAGE_EGL_IMAGE))) {
      assert(!info->synchronized);
      return virgl_gbm_transfer(res->gbm_bo, transfer_mode, iov, num_iovs, info);
   }
#endif

   if (!check_transfer_bounds(res, info)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_TRANSFER_IOV_BOUNDS, res->id);
      return EINVAL;
   }

   if (!check_iov_bounds(res, info, iov, num_iovs)) {
      vrend_report_context_error(ctx, VIRGL_ERROR_CTX_TRANSFER_IOV_BOUNDS, res->id);
      return EINVAL;
   }

   switch (transfer_mode) {
   case VIRGL_TRANSFER_TO_HOST:
      return vrend_renderer_transfer_write_iov(ctx, res, iov, num_iovs, info);
   case VIRGL_TRANSFER_FROM_HOST:
      return vrend_renderer_transfer_send_iov(ctx, res, iov, num_iovs, info);

   default:
      assert(0);
   }
   return 0;
}