diff options
author | Zach Reizner <zachr@google.com> | 2018-09-05 10:23:46 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-12-14 22:40:45 -0800 |
commit | c5899296c41f9c3991542350a3e2e6118e1972c2 (patch) | |
tree | 1e2f931efa7ca712841748870531f0add5ce683f /devices | |
parent | 200fd78ff1fb7849e47e99ae3f71a2fb7cc0e493 (diff) | |
download | crosvm-c5899296c41f9c3991542350a3e2e6118e1972c2.tar crosvm-c5899296c41f9c3991542350a3e2e6118e1972c2.tar.gz crosvm-c5899296c41f9c3991542350a3e2e6118e1972c2.tar.bz2 crosvm-c5899296c41f9c3991542350a3e2e6118e1972c2.tar.lz crosvm-c5899296c41f9c3991542350a3e2e6118e1972c2.tar.xz crosvm-c5899296c41f9c3991542350a3e2e6118e1972c2.tar.zst crosvm-c5899296c41f9c3991542350a3e2e6118e1972c2.zip |
devices: gpu: add plane info response support
In order to properly send dmabufs over the wayland protocol, accurate buffer metadata is needed in the guest. This change plumbs information from minigbm allocations to the guest using a virtio-gpu response. BUG=875998 TEST=wayland-simple-egl Change-Id: I5c80d539bc7757c302ad7adf56f5d3b011304617 Reviewed-on: https://chromium-review.googlesource.com/1227054 Commit-Ready: Zach Reizner <zachr@chromium.org> Tested-by: Zach Reizner <zachr@chromium.org> Reviewed-by: David Riley <davidriley@chromium.org>
Diffstat (limited to 'devices')
-rw-r--r-- | devices/src/virtio/gpu/backend.rs | 18 | ||||
-rw-r--r-- | devices/src/virtio/gpu/protocol.rs | 76 |
2 files changed, 90 insertions, 4 deletions
diff --git a/devices/src/virtio/gpu/backend.rs b/devices/src/virtio/gpu/backend.rs index 139fd43..b8f98e4 100644 --- a/devices/src/virtio/gpu/backend.rs +++ b/devices/src/virtio/gpu/backend.rs @@ -24,8 +24,9 @@ use super::gpu_renderer::{ }; use super::super::resource_bridge::*; -use super::protocol::GpuResponse; -use super::protocol::{VIRTIO_GPU_CAPSET_VIRGL, VIRTIO_GPU_CAPSET_VIRGL2}; +use super::protocol::{ + GpuResponse, GpuResponsePlaneInfo, VIRTIO_GPU_CAPSET_VIRGL, VIRTIO_GPU_CAPSET_VIRGL2, +}; const DEFAULT_WIDTH: u32 = 1280; const DEFAULT_HEIGHT: u32 = 1024; @@ -798,10 +799,21 @@ impl Backend { let res = self.renderer.import_resource(create_args, &image); match res { Ok(res) => { + let format_modifier = buffer.format_modifier(); + let mut plane_info = Vec::with_capacity(buffer.num_planes()); + for plane_index in 0..buffer.num_planes() { + plane_info.push(GpuResponsePlaneInfo { + stride: buffer.plane_stride(plane_index), + offset: buffer.plane_offset(plane_index), + }); + } let mut backed = BackedBuffer::new_renderer_registered(buffer, res, image); slot.insert(Box::new(backed)); - GpuResponse::OkNoData + GpuResponse::OkResourcePlaneInfo { + format_modifier, + plane_info, + } } Err(e) => { error!("failed to import renderer resource: {}", e); diff --git a/devices/src/virtio/gpu/protocol.rs b/devices/src/virtio/gpu/protocol.rs index f3e53a8..8ed6b02 100644 --- a/devices/src/virtio/gpu/protocol.rs +++ b/devices/src/virtio/gpu/protocol.rs @@ -44,6 +44,7 @@ pub const VIRTIO_GPU_RESP_OK_NODATA: u32 = 0x1100; pub const VIRTIO_GPU_RESP_OK_DISPLAY_INFO: u32 = 0x1101; pub const VIRTIO_GPU_RESP_OK_CAPSET_INFO: u32 = 0x1102; pub const VIRTIO_GPU_RESP_OK_CAPSET: u32 = 0x1103; +pub const VIRTIO_GPU_RESP_OK_RESOURCE_PLANE_INFO: u32 = 0x1104; /* error responses */ pub const VIRTIO_GPU_RESP_ERR_UNSPEC: u32 = 0x1200; @@ -79,6 +80,7 @@ pub fn virtio_gpu_cmd_str(cmd: u32) -> &'static str { VIRTIO_GPU_RESP_OK_DISPLAY_INFO => "VIRTIO_GPU_RESP_OK_DISPLAY_INFO", VIRTIO_GPU_RESP_OK_CAPSET_INFO => "VIRTIO_GPU_RESP_OK_CAPSET_INFO", VIRTIO_GPU_RESP_OK_CAPSET => "VIRTIO_GPU_RESP_OK_CAPSET", + VIRTIO_GPU_RESP_OK_RESOURCE_PLANE_INFO => "VIRTIO_GPU_RESP_OK_RESOURCE_PLANE_INFO", VIRTIO_GPU_RESP_ERR_UNSPEC => "VIRTIO_GPU_RESP_ERR_UNSPEC", VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY => "VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY", VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID => "VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID", @@ -417,6 +419,22 @@ pub struct virtio_gpu_resp_capset { unsafe impl DataInit for virtio_gpu_resp_capset {} +/* VIRTIO_GPU_RESP_OK_RESOURCE_PLANE_INFO */ +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct virtio_gpu_resp_resource_plane_info { + pub hdr: virtio_gpu_ctrl_hdr, + pub count: Le32, + pub padding: Le32, + pub format_modifier: Le64, + pub strides: [Le32; 4], + pub offsets: [Le32; 4], +} + +unsafe impl DataInit for virtio_gpu_resp_resource_plane_info {} + +const PLANE_INFO_MAX_COUNT: usize = 4; + pub const VIRTIO_GPU_EVENT_DISPLAY: u32 = 1 << 0; #[derive(Copy, Clone, Debug)] @@ -567,13 +585,27 @@ impl GpuCommand { } } +#[derive(Debug, PartialEq)] +pub struct GpuResponsePlaneInfo { + pub stride: u32, + pub offset: u32, +} + /// A response to a `GpuCommand`. These correspond to `VIRTIO_GPU_RESP_*`. #[derive(Debug, PartialEq)] pub enum GpuResponse { OkNoData, OkDisplayInfo(Vec<(u32, u32)>), - OkCapsetInfo { id: u32, version: u32, size: u32 }, + OkCapsetInfo { + id: u32, + version: u32, + size: u32, + }, OkCapset(Vec<u8>), + OkResourcePlaneInfo { + format_modifier: u64, + plane_info: Vec<GpuResponsePlaneInfo>, + }, ErrUnspec, ErrOutOfMemory, ErrInvalidScanoutId, @@ -589,6 +621,8 @@ pub enum GpuResponseEncodeError { Memory(VolatileMemoryError), /// More displays than are valid were in a `OkDisplayInfo`. TooManyDisplays(usize), + /// More planes than are valid were in a `OkResourcePlaneInfo`. + TooManyPlanes(usize), } impl From<VolatileMemoryError> for GpuResponseEncodeError { @@ -647,6 +681,44 @@ impl GpuResponse { resp_data_slice.copy_from(data); size_of_val(&hdr) + data.len() } + GpuResponse::OkResourcePlaneInfo { + format_modifier, + ref plane_info, + } => { + if plane_info.len() > PLANE_INFO_MAX_COUNT { + return Err(GpuResponseEncodeError::TooManyPlanes(plane_info.len())); + } + let mut strides = [Le32::default(); PLANE_INFO_MAX_COUNT]; + let mut offsets = [Le32::default(); PLANE_INFO_MAX_COUNT]; + for (plane_index, plane) in plane_info.iter().enumerate() { + strides[plane_index] = plane.stride.into(); + offsets[plane_index] = plane.offset.into(); + } + let plane_info = virtio_gpu_resp_resource_plane_info { + hdr, + count: Le32::from(plane_info.len() as u32), + padding: 0.into(), + format_modifier: format_modifier.into(), + strides, + offsets, + }; + match resp.get_ref(0) { + Ok(resp_ref) => { + resp_ref.store(plane_info); + size_of_val(&plane_info) + } + _ => { + // In case there is too little room in the response slice to store the + // entire virtio_gpu_resp_resource_plane_info, convert response to a regular + // VIRTIO_GPU_RESP_OK_NODATA and attempt to return that. + resp.get_ref(0)?.store(virtio_gpu_ctrl_hdr { + type_: Le32::from(VIRTIO_GPU_RESP_OK_NODATA), + ..hdr + }); + size_of_val(&hdr) + } + } + } _ => { resp.get_ref(0)?.store(hdr); size_of_val(&hdr) @@ -662,6 +734,7 @@ impl GpuResponse { GpuResponse::OkDisplayInfo(_) => VIRTIO_GPU_RESP_OK_DISPLAY_INFO, GpuResponse::OkCapsetInfo { .. } => VIRTIO_GPU_RESP_OK_CAPSET_INFO, GpuResponse::OkCapset(_) => VIRTIO_GPU_RESP_OK_CAPSET, + GpuResponse::OkResourcePlaneInfo { .. } => VIRTIO_GPU_RESP_OK_RESOURCE_PLANE_INFO, GpuResponse::ErrUnspec => VIRTIO_GPU_RESP_ERR_UNSPEC, GpuResponse::ErrOutOfMemory => VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY, GpuResponse::ErrInvalidScanoutId => VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID, @@ -678,6 +751,7 @@ impl GpuResponse { GpuResponse::OkDisplayInfo(_) => true, GpuResponse::OkCapsetInfo { .. } => true, GpuResponse::OkCapset(_) => true, + GpuResponse::OkResourcePlaneInfo { .. } => true, _ => false, } } |