static bool vrend_renderer_prepare_blit(struct vrend_context *ctx,
                                        struct vrend_resource *src_res,
                                        struct vrend_resource *dst_res,
                                        const struct vrend_blit_info *info)
{
   if (!info->can_fbo_blit)
      return false;

   /* if we can't make FBO's use the fallback path */
   if (!vrend_format_can_render(src_res->base.format) &&
       !vrend_format_is_ds(src_res->base.format))
      return false;

   if (!vrend_format_can_render(src_res->base.format) &&
       !vrend_format_is_ds(src_res->base.format))
      return false;

   /* different depth formats */
   if (vrend_format_is_ds(src_res->base.format) &&
       vrend_format_is_ds(dst_res->base.format)) {
      if (src_res->base.format != dst_res->base.format) {
         if (!(src_res->base.format == PIPE_FORMAT_S8_UINT_Z24_UNORM &&
               (dst_res->base.format == PIPE_FORMAT_Z24X8_UNORM))) {
            return false;
         }
      }
   }
   /* glBlitFramebuffer - can support depth stencil with NEAREST
      which we use for mipmaps */
   if ((info->b.mask & (PIPE_MASK_Z | PIPE_MASK_S)) && info->gl_filter == PIPE_TEX_FILTER_LINEAR)
      return false;

   /* since upstream mesa change
    * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5034
    * an imported RGBX texture uses GL_RGB8 as internal format while
    * in virgl_formats, we use GL_RGBA8 internal format for RGBX texutre.
    * on GLES host, glBlitFramebuffer doesn't work in such case. */
   if (vrend_state.use_gles &&
       info->b.mask & PIPE_MASK_RGBA &&
       src_res->base.format == VIRGL_FORMAT_R8G8B8X8_UNORM &&
       dst_res->base.format == VIRGL_FORMAT_R8G8B8X8_UNORM &&
       has_bit(src_res->storage_bits, VREND_STORAGE_EGL_IMAGE) !=
       has_bit(dst_res->storage_bits, VREND_STORAGE_EGL_IMAGE) &&
       (src_res->base.nr_samples || dst_res->base.nr_samples)) {
      return false;
   }

   /* GLES generally doesn't support blitting to a multi-sample FB, and also not
    * from a multi-sample FB where the regions are not exatly the same or the
    * source and target format are different. For
    * downsampling DS blits to zero samples we solve this by doing two blits */
   if (vrend_state.use_gles &&
       ((dst_res->base.nr_samples > 0) ||
        ((info->b.mask & PIPE_MASK_RGBA) &&
         (src_res->base.nr_samples > 0) &&
         (info->b.src.box.x != info->b.dst.box.x ||
          info->b.src.box.width != info->b.dst.box.width ||
          info->dst_y1 != info->src_y1 || info->dst_y2 != info->src_y2 ||
          info->b.src.format != info->b.dst.format))
        )) {
      VREND_DEBUG(dbg_blit, ctx, "Use GL fallback because dst:ms:%d src:ms:%d (%d %d %d %d) -> (%d %d %d %d)\n",
                  dst_res->base.nr_samples, src_res->base.nr_samples, info->b.src.box.x, info->b.src.box.x + info->b.src.box.width,
                  info->src_y1, info->src_y2, info->b.dst.box.x, info->b.dst.box.x + info->b.dst.box.width, info->dst_y1, info->dst_y2);
         return false;
   }

   /* for 3D mipmapped blits - hand roll time */
   if (info->b.src.box.depth != info->b.dst.box.depth)
      return false;

   return true;
}