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 <zachr@chromium.org>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
This commit is contained in:
Gurchetan Singh 2020-07-23 16:34:12 -07:00 committed by Commit Bot
parent ca3817bda3
commit fb72b4708b
3 changed files with 87 additions and 28 deletions

View file

@ -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<resource>
.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,
),

View file

@ -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)]

View file

@ -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<VirglVec>,
backing_mem: Option<GuestMemory>,
}
@ -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<File> {
#[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<File> {
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)]