From fb72b4708b907344b09602d7bab54ea1049cab8e Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Thu, 23 Jul 2020 16:34:12 -0700 Subject: [PATCH] devices: gpu: virgl_renderer_resource_export_blob With blob resources, there's a new export API. BUG=chromium:924405 TEST=local testing with blobs Change-Id: I4a6a48608fd6910b6deea53ef54f94def1799950 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2349395 Reviewed-by: Zach Reizner Tested-by: Gurchetan Singh Commit-Queue: Gurchetan Singh --- devices/src/virtio/gpu/virtio_3d_backend.rs | 66 +++++++++++++-------- gpu_renderer/src/generated/virglrenderer.rs | 9 +++ gpu_renderer/src/lib.rs | 40 ++++++++++++- 3 files changed, 87 insertions(+), 28 deletions(-) diff --git a/devices/src/virtio/gpu/virtio_3d_backend.rs b/devices/src/virtio/gpu/virtio_3d_backend.rs index bc90fd75a9..c0bf801fc8 100644 --- a/devices/src/virtio/gpu/virtio_3d_backend.rs +++ b/devices/src/virtio/gpu/virtio_3d_backend.rs @@ -13,8 +13,6 @@ use std::rc::Rc; use std::sync::Arc; use std::usize; -use libc::EINVAL; - use base::{error, warn, Error, ExternalMapping}; use data_model::*; use msg_socket::{MsgReceiver, MsgSender}; @@ -24,8 +22,8 @@ use vm_memory::{GuestAddress, GuestMemory}; use gpu_display::*; use gpu_renderer::{ - Box3, Context as RendererContext, Error as GpuRendererError, Renderer, RendererFlags, - Resource as GpuRendererResource, ResourceCreateArgs, + Box3, Context as RendererContext, Renderer, RendererFlags, Resource as GpuRendererResource, + ResourceCreateArgs, }; use super::protocol::{ @@ -110,14 +108,8 @@ impl VirtioResource for Virtio3DResource { } } - let (query, dmabuf) = match self.gpu_resource.export() { - Ok(export) => (export.0, export.1), - Err(GpuRendererError::Virglrenderer(e)) if e == -EINVAL => return None, - Err(e) => { - error!("failed to query resource: {}", e); - return None; - } - }; + let dmabuf = self.gpu_resource.export().ok()?; + let query = self.gpu_resource.query().ok()?; let (width, height, format, stride, offset) = match self.scanout_data { Some(data) => ( @@ -349,18 +341,42 @@ impl Backend for Virtio3DBackend { /// If supported, export the resource with the given id to a file. fn export_resource(&mut self, id: u32) -> ResourceResponse { - self - .resources - .get(&id) // Option - .and_then(|resource| resource.gpu_resource.export().ok()) // Option<(Query, File)> - .map(|(q, file)| { - ResourceResponse::Resource(ResourceInfo{file, planes: [ - PlaneInfo{offset: q.out_offsets[0], stride: q.out_strides[0]}, - PlaneInfo{offset: q.out_offsets[1], stride: q.out_strides[1]}, - PlaneInfo{offset: q.out_offsets[2], stride: q.out_strides[2]}, - PlaneInfo{offset: q.out_offsets[3], stride: q.out_strides[3]}, - ]}) - }).unwrap_or(ResourceResponse::Invalid) + let resource = match self.resources.get_mut(&id) { + Some(r) => r, + None => return ResourceResponse::Invalid, + }; + + let q = match resource.gpu_resource.query() { + Ok(query) => query, + Err(_) => return ResourceResponse::Invalid, + }; + + let file = match resource.gpu_resource.export() { + Ok(file) => file, + Err(_) => return ResourceResponse::Invalid, + }; + + ResourceResponse::Resource(ResourceInfo { + file, + planes: [ + PlaneInfo { + offset: q.out_offsets[0], + stride: q.out_strides[0], + }, + PlaneInfo { + offset: q.out_offsets[1], + stride: q.out_strides[1], + }, + PlaneInfo { + offset: q.out_offsets[2], + stride: q.out_strides[2], + }, + PlaneInfo { + offset: q.out_offsets[3], + stride: q.out_strides[3], + }, + ], + }) } /// Creates a fence with the given id that can be used to determine when the previous command @@ -879,7 +895,7 @@ impl Backend for Virtio3DBackend { let request = match export { Ok(ref export) => VmMemoryRequest::RegisterFdAtPciBarOffset( self.pci_bar, - MaybeOwnedFd::Borrowed(export.1.as_raw_fd()), + MaybeOwnedFd::Borrowed(export.as_raw_fd()), resource.size as usize, offset, ), diff --git a/gpu_renderer/src/generated/virglrenderer.rs b/gpu_renderer/src/generated/virglrenderer.rs index f2d5554b86..7fbf191875 100644 --- a/gpu_renderer/src/generated/virglrenderer.rs +++ b/gpu_renderer/src/generated/virglrenderer.rs @@ -21,6 +21,8 @@ pub const VIRGL_RES_BIND_CURSOR: u32 = 65536; pub const VIRGL_RES_BIND_CUSTOM: u32 = 131072; pub const VIRGL_RES_BIND_SCANOUT: u32 = 262144; pub const VIRGL_RES_BIND_SHARED: u32 = 1048576; +pub const VIRGL_RENDERER_BLOB_FD_TYPE_DMABUF: u32 = 1; +pub const VIRGL_RENDERER_BLOB_FD_TYPE_OPAQUE: u32 = 2; pub type __int32_t = ::std::os::raw::c_int; pub type __uint32_t = ::std::os::raw::c_uint; pub type __uint64_t = ::std::os::raw::c_ulong; @@ -341,6 +343,13 @@ extern "C" { map_info: *mut u32, ) -> ::std::os::raw::c_int; } +extern "C" { + pub fn virgl_renderer_resource_export_blob( + res_id: u32, + fd_type: *mut u32, + fd: *mut ::std::os::raw::c_int, + ) -> ::std::os::raw::c_int; +} pub type __builtin_va_list = [__va_list_tag; 1usize]; #[repr(C)] #[derive(Debug, Copy, Clone)] diff --git a/gpu_renderer/src/lib.rs b/gpu_renderer/src/lib.rs index 7707ddc9a3..c7351707a1 100644 --- a/gpu_renderer/src/lib.rs +++ b/gpu_renderer/src/lib.rs @@ -338,6 +338,7 @@ impl Renderer { ret_to_res(ret)?; Ok(Resource { id: args.handle, + blob: false, backing_iovecs: Vec::new(), backing_mem: None, }) @@ -463,6 +464,7 @@ impl Renderer { Ok(Resource { id: resource_id, + blob: true, backing_iovecs: iovecs, backing_mem: None, }) @@ -585,6 +587,7 @@ fn unmap_func(resource_id: u32) { /// A resource handle used by the renderer. pub struct Resource { id: u32, + blob: bool, backing_iovecs: Vec, backing_mem: Option, } @@ -618,8 +621,39 @@ impl Resource { self.export_query(false) } - /// Returns resource metadata and exports the associated dma-buf. - pub fn export(&self) -> Result<(Query, File)> { + /// Exports the associated dma-buf for a blob resource. + fn export_blob(&self) -> Result { + #[cfg(feature = "virtio-gpu-next")] + { + let mut fd_type = 0; + let mut fd = 0; + let ret = unsafe { + virgl_renderer_resource_export_blob(self.id as u32, &mut fd_type, &mut fd) + }; + ret_to_res(ret)?; + + /* Only support dma-bufs until someone wants opaque fds too. */ + if fd_type != VIRGL_RENDERER_BLOB_FD_TYPE_DMABUF { + // Safe because the FD was just returned by a successful virglrenderer + // call so it must be valid and owned by us. + unsafe { close(fd) }; + return Err(Error::Unsupported); + } + + let dmabuf = unsafe { File::from_raw_fd(fd) }; + Ok(dmabuf) + } + #[cfg(not(feature = "virtio-gpu-next"))] + Err(Error::Unsupported) + } + + /// Exports the associated dma-buf for a blob resource and traditional virtio-gpu resource + /// backed by a dma-buf. + pub fn export(&self) -> Result { + if self.blob { + return self.export_blob(); + } + let query = self.export_query(true)?; if query.out_num_fds != 1 || query.out_fds[0] < 0 { for fd in &query.out_fds { @@ -635,7 +669,7 @@ impl Resource { // Safe because the FD was just returned by a successful virglrenderer call so it must // be valid and owned by us. let dmabuf = unsafe { File::from_raw_fd(query.out_fds[0]) }; - Ok((query, dmabuf)) + Ok(dmabuf) } #[allow(unused_variables)]