xref: /aosp_15_r20/external/crosvm/vm_control/src/gpu.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap as Map;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Display;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
11*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
12*bb4ee6a4SAndroid Build Coastguard Worker use serde_keyvalue::FromKeyValues;
13*bb4ee6a4SAndroid Build Coastguard Worker 
14*bb4ee6a4SAndroid Build Coastguard Worker pub use crate::sys::handle_request;
15*bb4ee6a4SAndroid Build Coastguard Worker pub use crate::sys::DisplayMode;
16*bb4ee6a4SAndroid Build Coastguard Worker pub use crate::sys::MouseMode;
17*bb4ee6a4SAndroid Build Coastguard Worker pub use crate::*;
18*bb4ee6a4SAndroid Build Coastguard Worker 
19*bb4ee6a4SAndroid Build Coastguard Worker pub const DEFAULT_DISPLAY_WIDTH: u32 = 1280;
20*bb4ee6a4SAndroid Build Coastguard Worker pub const DEFAULT_DISPLAY_HEIGHT: u32 = 1024;
21*bb4ee6a4SAndroid Build Coastguard Worker pub const DEFAULT_DPI: u32 = 320;
22*bb4ee6a4SAndroid Build Coastguard Worker pub const DEFAULT_REFRESH_RATE: u32 = 60;
23*bb4ee6a4SAndroid Build Coastguard Worker 
default_refresh_rate() -> u3224*bb4ee6a4SAndroid Build Coastguard Worker fn default_refresh_rate() -> u32 {
25*bb4ee6a4SAndroid Build Coastguard Worker     DEFAULT_REFRESH_RATE
26*bb4ee6a4SAndroid Build Coastguard Worker }
27*bb4ee6a4SAndroid Build Coastguard Worker 
28*bb4ee6a4SAndroid Build Coastguard Worker /// Trait that the platform-specific type `DisplayMode` needs to implement.
29*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) trait DisplayModeTrait {
30*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the initial host window size.
get_window_size(&self) -> (u32, u32)31*bb4ee6a4SAndroid Build Coastguard Worker     fn get_window_size(&self) -> (u32, u32);
32*bb4ee6a4SAndroid Build Coastguard Worker 
33*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the virtual display size used for creating the display device.
34*bb4ee6a4SAndroid Build Coastguard Worker     ///
35*bb4ee6a4SAndroid Build Coastguard Worker     /// We need to query the phenotype flags to see if resolutions higher than 1080p should be
36*bb4ee6a4SAndroid Build Coastguard Worker     /// enabled. This functions assumes process invariants have been set up and phenotype flags are
37*bb4ee6a4SAndroid Build Coastguard Worker     /// available. If not, use `get_virtual_display_size_4k_uhd()` instead.
38*bb4ee6a4SAndroid Build Coastguard Worker     ///
39*bb4ee6a4SAndroid Build Coastguard Worker     /// This may be different from the initial host window size since different display backends may
40*bb4ee6a4SAndroid Build Coastguard Worker     /// have different alignment requirements on it.
get_virtual_display_size(&self) -> (u32, u32)41*bb4ee6a4SAndroid Build Coastguard Worker     fn get_virtual_display_size(&self) -> (u32, u32);
42*bb4ee6a4SAndroid Build Coastguard Worker 
43*bb4ee6a4SAndroid Build Coastguard Worker     /// Returns the virtual display size used for creating the display device.
44*bb4ee6a4SAndroid Build Coastguard Worker     ///
45*bb4ee6a4SAndroid Build Coastguard Worker     /// While `get_virtual_display_size()` reads phenotype flags internally, this function does not,
46*bb4ee6a4SAndroid Build Coastguard Worker     /// so it can be used when process invariants and phenotype flags are not yet ready.
get_virtual_display_size_4k_uhd(&self, is_4k_uhd_enabled: bool) -> (u32, u32)47*bb4ee6a4SAndroid Build Coastguard Worker     fn get_virtual_display_size_4k_uhd(&self, is_4k_uhd_enabled: bool) -> (u32, u32);
48*bb4ee6a4SAndroid Build Coastguard Worker }
49*bb4ee6a4SAndroid Build Coastguard Worker 
50*bb4ee6a4SAndroid Build Coastguard Worker impl Default for DisplayMode {
default() -> Self51*bb4ee6a4SAndroid Build Coastguard Worker     fn default() -> Self {
52*bb4ee6a4SAndroid Build Coastguard Worker         Self::Windowed(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT)
53*bb4ee6a4SAndroid Build Coastguard Worker     }
54*bb4ee6a4SAndroid Build Coastguard Worker }
55*bb4ee6a4SAndroid Build Coastguard Worker 
56*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromKeyValues)]
57*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields, rename_all = "kebab-case")]
58*bb4ee6a4SAndroid Build Coastguard Worker pub struct DisplayParameters {
59*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default)]
60*bb4ee6a4SAndroid Build Coastguard Worker     pub mode: DisplayMode,
61*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default)]
62*bb4ee6a4SAndroid Build Coastguard Worker     pub hidden: bool,
63*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default = "default_refresh_rate")]
64*bb4ee6a4SAndroid Build Coastguard Worker     pub refresh_rate: u32,
65*bb4ee6a4SAndroid Build Coastguard Worker     // TODO(b/260101753): `dpi` has to be an `Option` for supporting CLI backward compatibility.
66*bb4ee6a4SAndroid Build Coastguard Worker     // That should be changed once compat fields below are deprecated.
67*bb4ee6a4SAndroid Build Coastguard Worker     pub dpi: Option<(u32, u32)>,
68*bb4ee6a4SAndroid Build Coastguard Worker     // `horizontal-dpi` and `vertical-dpi` are supported for CLI backward compatibility.
69*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(rename = "horizontal-dpi")]
70*bb4ee6a4SAndroid Build Coastguard Worker     pub __horizontal_dpi_compat: Option<u32>,
71*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(rename = "vertical-dpi")]
72*bb4ee6a4SAndroid Build Coastguard Worker     pub __vertical_dpi_compat: Option<u32>,
73*bb4ee6a4SAndroid Build Coastguard Worker }
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker impl DisplayParameters {
new( mode: DisplayMode, hidden: bool, refresh_rate: u32, horizontal_dpi: u32, vertical_dpi: u32, ) -> Self76*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(
77*bb4ee6a4SAndroid Build Coastguard Worker         mode: DisplayMode,
78*bb4ee6a4SAndroid Build Coastguard Worker         hidden: bool,
79*bb4ee6a4SAndroid Build Coastguard Worker         refresh_rate: u32,
80*bb4ee6a4SAndroid Build Coastguard Worker         horizontal_dpi: u32,
81*bb4ee6a4SAndroid Build Coastguard Worker         vertical_dpi: u32,
82*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Self {
83*bb4ee6a4SAndroid Build Coastguard Worker         Self {
84*bb4ee6a4SAndroid Build Coastguard Worker             mode,
85*bb4ee6a4SAndroid Build Coastguard Worker             hidden,
86*bb4ee6a4SAndroid Build Coastguard Worker             refresh_rate,
87*bb4ee6a4SAndroid Build Coastguard Worker             dpi: Some((horizontal_dpi, vertical_dpi)),
88*bb4ee6a4SAndroid Build Coastguard Worker             __horizontal_dpi_compat: None,
89*bb4ee6a4SAndroid Build Coastguard Worker             __vertical_dpi_compat: None,
90*bb4ee6a4SAndroid Build Coastguard Worker         }
91*bb4ee6a4SAndroid Build Coastguard Worker     }
92*bb4ee6a4SAndroid Build Coastguard Worker 
default_with_mode(mode: DisplayMode) -> Self93*bb4ee6a4SAndroid Build Coastguard Worker     pub fn default_with_mode(mode: DisplayMode) -> Self {
94*bb4ee6a4SAndroid Build Coastguard Worker         Self::new(mode, false, DEFAULT_REFRESH_RATE, DEFAULT_DPI, DEFAULT_DPI)
95*bb4ee6a4SAndroid Build Coastguard Worker     }
96*bb4ee6a4SAndroid Build Coastguard Worker 
get_window_size(&self) -> (u32, u32)97*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_window_size(&self) -> (u32, u32) {
98*bb4ee6a4SAndroid Build Coastguard Worker         self.mode.get_window_size()
99*bb4ee6a4SAndroid Build Coastguard Worker     }
100*bb4ee6a4SAndroid Build Coastguard Worker 
get_virtual_display_size(&self) -> (u32, u32)101*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_virtual_display_size(&self) -> (u32, u32) {
102*bb4ee6a4SAndroid Build Coastguard Worker         self.mode.get_virtual_display_size()
103*bb4ee6a4SAndroid Build Coastguard Worker     }
104*bb4ee6a4SAndroid Build Coastguard Worker 
get_virtual_display_size_4k_uhd(&self, is_4k_uhd_enabled: bool) -> (u32, u32)105*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_virtual_display_size_4k_uhd(&self, is_4k_uhd_enabled: bool) -> (u32, u32) {
106*bb4ee6a4SAndroid Build Coastguard Worker         self.mode.get_virtual_display_size_4k_uhd(is_4k_uhd_enabled)
107*bb4ee6a4SAndroid Build Coastguard Worker     }
108*bb4ee6a4SAndroid Build Coastguard Worker 
horizontal_dpi(&self) -> u32109*bb4ee6a4SAndroid Build Coastguard Worker     pub fn horizontal_dpi(&self) -> u32 {
110*bb4ee6a4SAndroid Build Coastguard Worker         self.dpi.expect("'dpi' is None").0
111*bb4ee6a4SAndroid Build Coastguard Worker     }
112*bb4ee6a4SAndroid Build Coastguard Worker 
vertical_dpi(&self) -> u32113*bb4ee6a4SAndroid Build Coastguard Worker     pub fn vertical_dpi(&self) -> u32 {
114*bb4ee6a4SAndroid Build Coastguard Worker         self.dpi.expect("'dpi' is None").1
115*bb4ee6a4SAndroid Build Coastguard Worker     }
116*bb4ee6a4SAndroid Build Coastguard Worker }
117*bb4ee6a4SAndroid Build Coastguard Worker 
118*bb4ee6a4SAndroid Build Coastguard Worker impl Default for DisplayParameters {
default() -> Self119*bb4ee6a4SAndroid Build Coastguard Worker     fn default() -> Self {
120*bb4ee6a4SAndroid Build Coastguard Worker         Self::default_with_mode(Default::default())
121*bb4ee6a4SAndroid Build Coastguard Worker     }
122*bb4ee6a4SAndroid Build Coastguard Worker }
123*bb4ee6a4SAndroid Build Coastguard Worker 
124*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Debug)]
125*bb4ee6a4SAndroid Build Coastguard Worker pub enum GpuControlCommand {
126*bb4ee6a4SAndroid Build Coastguard Worker     AddDisplays {
127*bb4ee6a4SAndroid Build Coastguard Worker         displays: Vec<DisplayParameters>,
128*bb4ee6a4SAndroid Build Coastguard Worker     },
129*bb4ee6a4SAndroid Build Coastguard Worker     ListDisplays,
130*bb4ee6a4SAndroid Build Coastguard Worker     RemoveDisplays {
131*bb4ee6a4SAndroid Build Coastguard Worker         display_ids: Vec<u32>,
132*bb4ee6a4SAndroid Build Coastguard Worker     },
133*bb4ee6a4SAndroid Build Coastguard Worker     SetDisplayMouseMode {
134*bb4ee6a4SAndroid Build Coastguard Worker         display_id: u32,
135*bb4ee6a4SAndroid Build Coastguard Worker         mouse_mode: MouseMode,
136*bb4ee6a4SAndroid Build Coastguard Worker     },
137*bb4ee6a4SAndroid Build Coastguard Worker }
138*bb4ee6a4SAndroid Build Coastguard Worker 
139*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Serialize, Deserialize, Debug, Clone)]
140*bb4ee6a4SAndroid Build Coastguard Worker pub enum GpuControlResult {
141*bb4ee6a4SAndroid Build Coastguard Worker     DisplaysUpdated,
142*bb4ee6a4SAndroid Build Coastguard Worker     DisplayList {
143*bb4ee6a4SAndroid Build Coastguard Worker         displays: Map<u32, DisplayParameters>,
144*bb4ee6a4SAndroid Build Coastguard Worker     },
145*bb4ee6a4SAndroid Build Coastguard Worker     TooManyDisplays {
146*bb4ee6a4SAndroid Build Coastguard Worker         allowed: usize,
147*bb4ee6a4SAndroid Build Coastguard Worker         requested: usize,
148*bb4ee6a4SAndroid Build Coastguard Worker     },
149*bb4ee6a4SAndroid Build Coastguard Worker     NoSuchDisplay {
150*bb4ee6a4SAndroid Build Coastguard Worker         display_id: u32,
151*bb4ee6a4SAndroid Build Coastguard Worker     },
152*bb4ee6a4SAndroid Build Coastguard Worker     DisplayMouseModeSet,
153*bb4ee6a4SAndroid Build Coastguard Worker     ErrString(String),
154*bb4ee6a4SAndroid Build Coastguard Worker }
155*bb4ee6a4SAndroid Build Coastguard Worker 
156*bb4ee6a4SAndroid Build Coastguard Worker impl Display for GpuControlResult {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result157*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
158*bb4ee6a4SAndroid Build Coastguard Worker         use self::GpuControlResult::*;
159*bb4ee6a4SAndroid Build Coastguard Worker 
160*bb4ee6a4SAndroid Build Coastguard Worker         match self {
161*bb4ee6a4SAndroid Build Coastguard Worker             DisplaysUpdated => write!(f, "displays updated"),
162*bb4ee6a4SAndroid Build Coastguard Worker             DisplayList { displays } => {
163*bb4ee6a4SAndroid Build Coastguard Worker                 let json: serde_json::Value = serde_json::json!({
164*bb4ee6a4SAndroid Build Coastguard Worker                     "displays": displays,
165*bb4ee6a4SAndroid Build Coastguard Worker                 });
166*bb4ee6a4SAndroid Build Coastguard Worker                 let json_pretty =
167*bb4ee6a4SAndroid Build Coastguard Worker                     serde_json::to_string_pretty(&json).map_err(|_| std::fmt::Error)?;
168*bb4ee6a4SAndroid Build Coastguard Worker                 write!(f, "{}", json_pretty)
169*bb4ee6a4SAndroid Build Coastguard Worker             }
170*bb4ee6a4SAndroid Build Coastguard Worker             TooManyDisplays { allowed, requested } => write!(
171*bb4ee6a4SAndroid Build Coastguard Worker                 f,
172*bb4ee6a4SAndroid Build Coastguard Worker                 "too_many_displays: allowed {}, requested {}",
173*bb4ee6a4SAndroid Build Coastguard Worker                 allowed, requested
174*bb4ee6a4SAndroid Build Coastguard Worker             ),
175*bb4ee6a4SAndroid Build Coastguard Worker             NoSuchDisplay { display_id } => write!(f, "no_such_display {}", display_id),
176*bb4ee6a4SAndroid Build Coastguard Worker             DisplayMouseModeSet => write!(f, "display_mouse_mode_set"),
177*bb4ee6a4SAndroid Build Coastguard Worker             ErrString(reason) => write!(f, "err_string {}", reason),
178*bb4ee6a4SAndroid Build Coastguard Worker         }
179*bb4ee6a4SAndroid Build Coastguard Worker     }
180*bb4ee6a4SAndroid Build Coastguard Worker }
181*bb4ee6a4SAndroid Build Coastguard Worker 
182*bb4ee6a4SAndroid Build Coastguard Worker pub enum ModifyGpuError {
183*bb4ee6a4SAndroid Build Coastguard Worker     SocketFailed,
184*bb4ee6a4SAndroid Build Coastguard Worker     UnexpectedResponse(VmResponse),
185*bb4ee6a4SAndroid Build Coastguard Worker     UnknownCommand(String),
186*bb4ee6a4SAndroid Build Coastguard Worker     GpuControl(GpuControlResult),
187*bb4ee6a4SAndroid Build Coastguard Worker }
188*bb4ee6a4SAndroid Build Coastguard Worker 
189*bb4ee6a4SAndroid Build Coastguard Worker impl fmt::Display for ModifyGpuError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result190*bb4ee6a4SAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191*bb4ee6a4SAndroid Build Coastguard Worker         use self::ModifyGpuError::*;
192*bb4ee6a4SAndroid Build Coastguard Worker 
193*bb4ee6a4SAndroid Build Coastguard Worker         match self {
194*bb4ee6a4SAndroid Build Coastguard Worker             SocketFailed => write!(f, "socket failed"),
195*bb4ee6a4SAndroid Build Coastguard Worker             UnexpectedResponse(r) => write!(f, "unexpected response: {}", r),
196*bb4ee6a4SAndroid Build Coastguard Worker             UnknownCommand(c) => write!(f, "unknown display command: `{}`", c),
197*bb4ee6a4SAndroid Build Coastguard Worker             GpuControl(e) => write!(f, "{}", e),
198*bb4ee6a4SAndroid Build Coastguard Worker         }
199*bb4ee6a4SAndroid Build Coastguard Worker     }
200*bb4ee6a4SAndroid Build Coastguard Worker }
201*bb4ee6a4SAndroid Build Coastguard Worker 
202*bb4ee6a4SAndroid Build Coastguard Worker pub type ModifyGpuResult = std::result::Result<GpuControlResult, ModifyGpuError>;
203*bb4ee6a4SAndroid Build Coastguard Worker 
204*bb4ee6a4SAndroid Build Coastguard Worker impl From<VmResponse> for ModifyGpuResult {
from(response: VmResponse) -> Self205*bb4ee6a4SAndroid Build Coastguard Worker     fn from(response: VmResponse) -> Self {
206*bb4ee6a4SAndroid Build Coastguard Worker         match response {
207*bb4ee6a4SAndroid Build Coastguard Worker             VmResponse::GpuResponse(gpu_response) => Ok(gpu_response),
208*bb4ee6a4SAndroid Build Coastguard Worker             r => Err(ModifyGpuError::UnexpectedResponse(r)),
209*bb4ee6a4SAndroid Build Coastguard Worker         }
210*bb4ee6a4SAndroid Build Coastguard Worker     }
211*bb4ee6a4SAndroid Build Coastguard Worker }
212*bb4ee6a4SAndroid Build Coastguard Worker 
do_gpu_display_add<T: AsRef<Path> + std::fmt::Debug>( control_socket_path: T, displays: Vec<DisplayParameters>, ) -> ModifyGpuResult213*bb4ee6a4SAndroid Build Coastguard Worker pub fn do_gpu_display_add<T: AsRef<Path> + std::fmt::Debug>(
214*bb4ee6a4SAndroid Build Coastguard Worker     control_socket_path: T,
215*bb4ee6a4SAndroid Build Coastguard Worker     displays: Vec<DisplayParameters>,
216*bb4ee6a4SAndroid Build Coastguard Worker ) -> ModifyGpuResult {
217*bb4ee6a4SAndroid Build Coastguard Worker     let request = VmRequest::GpuCommand(GpuControlCommand::AddDisplays { displays });
218*bb4ee6a4SAndroid Build Coastguard Worker     handle_request(&request, control_socket_path)
219*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|_| ModifyGpuError::SocketFailed)?
220*bb4ee6a4SAndroid Build Coastguard Worker         .into()
221*bb4ee6a4SAndroid Build Coastguard Worker }
222*bb4ee6a4SAndroid Build Coastguard Worker 
do_gpu_display_list<T: AsRef<Path> + std::fmt::Debug>( control_socket_path: T, ) -> ModifyGpuResult223*bb4ee6a4SAndroid Build Coastguard Worker pub fn do_gpu_display_list<T: AsRef<Path> + std::fmt::Debug>(
224*bb4ee6a4SAndroid Build Coastguard Worker     control_socket_path: T,
225*bb4ee6a4SAndroid Build Coastguard Worker ) -> ModifyGpuResult {
226*bb4ee6a4SAndroid Build Coastguard Worker     let request = VmRequest::GpuCommand(GpuControlCommand::ListDisplays);
227*bb4ee6a4SAndroid Build Coastguard Worker     handle_request(&request, control_socket_path)
228*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|_| ModifyGpuError::SocketFailed)?
229*bb4ee6a4SAndroid Build Coastguard Worker         .into()
230*bb4ee6a4SAndroid Build Coastguard Worker }
231*bb4ee6a4SAndroid Build Coastguard Worker 
do_gpu_display_remove<T: AsRef<Path> + std::fmt::Debug>( control_socket_path: T, display_ids: Vec<u32>, ) -> ModifyGpuResult232*bb4ee6a4SAndroid Build Coastguard Worker pub fn do_gpu_display_remove<T: AsRef<Path> + std::fmt::Debug>(
233*bb4ee6a4SAndroid Build Coastguard Worker     control_socket_path: T,
234*bb4ee6a4SAndroid Build Coastguard Worker     display_ids: Vec<u32>,
235*bb4ee6a4SAndroid Build Coastguard Worker ) -> ModifyGpuResult {
236*bb4ee6a4SAndroid Build Coastguard Worker     let request = VmRequest::GpuCommand(GpuControlCommand::RemoveDisplays { display_ids });
237*bb4ee6a4SAndroid Build Coastguard Worker     handle_request(&request, control_socket_path)
238*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|_| ModifyGpuError::SocketFailed)?
239*bb4ee6a4SAndroid Build Coastguard Worker         .into()
240*bb4ee6a4SAndroid Build Coastguard Worker }
241*bb4ee6a4SAndroid Build Coastguard Worker 
do_gpu_set_display_mouse_mode<T: AsRef<Path> + std::fmt::Debug>( control_socket_path: T, display_id: u32, mouse_mode: MouseMode, ) -> ModifyGpuResult242*bb4ee6a4SAndroid Build Coastguard Worker pub fn do_gpu_set_display_mouse_mode<T: AsRef<Path> + std::fmt::Debug>(
243*bb4ee6a4SAndroid Build Coastguard Worker     control_socket_path: T,
244*bb4ee6a4SAndroid Build Coastguard Worker     display_id: u32,
245*bb4ee6a4SAndroid Build Coastguard Worker     mouse_mode: MouseMode,
246*bb4ee6a4SAndroid Build Coastguard Worker ) -> ModifyGpuResult {
247*bb4ee6a4SAndroid Build Coastguard Worker     let request = VmRequest::GpuCommand(GpuControlCommand::SetDisplayMouseMode {
248*bb4ee6a4SAndroid Build Coastguard Worker         display_id,
249*bb4ee6a4SAndroid Build Coastguard Worker         mouse_mode,
250*bb4ee6a4SAndroid Build Coastguard Worker     });
251*bb4ee6a4SAndroid Build Coastguard Worker     handle_request(&request, control_socket_path)
252*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|_| ModifyGpuError::SocketFailed)?
253*bb4ee6a4SAndroid Build Coastguard Worker         .into()
254*bb4ee6a4SAndroid Build Coastguard Worker }
255