From dd11d434730a5dea56106d0533bf42c6b7206ed0 Mon Sep 17 00:00:00 2001 From: Chirantan Ekbote Date: Tue, 11 Jun 2019 21:50:46 +0900 Subject: gpu: Allow more than one resource bridge socket Currently the wayland device accesses buffers allocated by the gpu device via a dedicated socket connection. Upcoming virtual devices like vdec and camera will also need access to these buffers. Modify the gpu device so that it can process requests on multiple resource_bridge sockets. Each future device that needs access to gpu device buffers should create a new resource bridge socket pair and add it to the list of sockets that the gpu device monitors. The actual interface between the devices is unchanged. BUG=b:133381367 TEST=run glxgears in a crostini container with and without gpu enabled Change-Id: I58693881945965071a53653bf4f86681725267d0 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1652876 Tested-by: kokoro Commit-Queue: Chirantan Ekbote Reviewed-by: Chirantan Ekbote Auto-Submit: Chirantan Ekbote --- devices/src/virtio/gpu/mod.rs | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'devices') diff --git a/devices/src/virtio/gpu/mod.rs b/devices/src/virtio/gpu/mod.rs index cc42ace..0031b73 100644 --- a/devices/src/virtio/gpu/mod.rs +++ b/devices/src/virtio/gpu/mod.rs @@ -8,7 +8,7 @@ mod protocol; use std::cell::RefCell; use std::collections::VecDeque; use std::i64; -use std::mem::size_of; +use std::mem::{self, size_of}; use std::os::unix::io::{AsRawFd, RawFd}; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -474,7 +474,7 @@ struct Worker { ctrl_evt: EventFd, cursor_queue: Queue, cursor_evt: EventFd, - resource_bridge: Option, + resource_bridges: Vec, kill_evt: EventFd, state: Frontend, } @@ -492,9 +492,9 @@ impl Worker { CtrlQueue, CursorQueue, Display, - ResourceBridge, InterruptResample, Kill, + ResourceBridge { index: usize }, } let poll_ctx: PollContext = match PollContext::new() @@ -517,12 +517,14 @@ impl Worker { } }; - if let Some(resource_bridge) = &self.resource_bridge { - if let Err(e) = poll_ctx.add(resource_bridge, Token::ResourceBridge) { + for (index, bridge) in self.resource_bridges.iter().enumerate() { + if let Err(e) = poll_ctx.add(bridge, Token::ResourceBridge { index }) { error!("failed to add resource bridge to PollContext: {}", e); } } + // Declare this outside the loop so we don't keep allocating and freeing the vector. + let mut process_resource_bridge = Vec::with_capacity(self.resource_bridges.len()); 'poll: loop { // If there are outstanding fences, wake up early to poll them. let duration = if !self.state.fence_descriptors.is_empty() { @@ -539,7 +541,11 @@ impl Worker { } }; let mut signal_used = false; - let mut process_resource_bridge = false; + + // Clear the old values and re-initialize with false. + process_resource_bridge.clear(); + process_resource_bridge.resize(self.resource_bridges.len(), false); + for event in events.iter_readable() { match event.token() { Token::CtrlQueue => { @@ -558,7 +564,7 @@ impl Worker { let _ = self.exit_evt.write(1); } } - Token::ResourceBridge => process_resource_bridge = true, + Token::ResourceBridge { index } => process_resource_bridge[index] = true, Token::InterruptResample => { let _ = self.interrupt_resample_evt.read(); if self.interrupt_status.load(Ordering::SeqCst) != 0 { @@ -587,9 +593,11 @@ impl Worker { // Process the entire control queue before the resource bridge in case a resource is // created or destroyed by the control queue. Processing the resource bridge first may // lead to a race condition. - if process_resource_bridge { - if let Some(resource_bridge) = &self.resource_bridge { - self.state.process_resource_bridge(resource_bridge); + for (bridge, &should_process) in + self.resource_bridges.iter().zip(&process_resource_bridge) + { + if should_process { + self.state.process_resource_bridge(bridge); } } @@ -604,7 +612,7 @@ pub struct Gpu { config_event: bool, exit_evt: EventFd, gpu_device_socket: Option, - resource_bridge: Option, + resource_bridges: Vec, kill_evt: Option, wayland_socket_path: PathBuf, } @@ -613,14 +621,14 @@ impl Gpu { pub fn new>( exit_evt: EventFd, gpu_device_socket: Option, - resource_bridge: Option, + resource_bridges: Vec, wayland_socket_path: P, ) -> Gpu { Gpu { config_event: false, exit_evt, gpu_device_socket, - resource_bridge, + resource_bridges, kill_evt: None, wayland_socket_path: wayland_socket_path.as_ref().to_path_buf(), } @@ -664,8 +672,8 @@ impl VirtioDevice for Gpu { } keep_fds.push(self.exit_evt.as_raw_fd()); - if let Some(resource_bridge) = &self.resource_bridge { - keep_fds.push(resource_bridge.as_raw_fd()); + for bridge in &self.resource_bridges { + keep_fds.push(bridge.as_raw_fd()); } keep_fds } @@ -739,7 +747,7 @@ impl VirtioDevice for Gpu { }; self.kill_evt = Some(self_kill_evt); - let resource_bridge = self.resource_bridge.take(); + let resource_bridges = mem::replace(&mut self.resource_bridges, Vec::new()); let ctrl_queue = queues.remove(0); let ctrl_evt = queue_evts.remove(0); @@ -802,7 +810,7 @@ impl VirtioDevice for Gpu { ctrl_evt, cursor_queue, cursor_evt, - resource_bridge, + resource_bridges, kill_evt, state: Frontend::new(Backend::new( device, -- cgit 1.4.1