• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::collections::BTreeMap as Map;
6 use std::fmt;
7 use std::fmt::Display;
8 use std::path::Path;
9 
10 use serde::Deserialize;
11 use serde::Serialize;
12 use serde_keyvalue::FromKeyValues;
13 
14 pub use crate::sys::handle_request;
15 pub use crate::sys::DisplayMode;
16 pub use crate::*;
17 
18 pub const DEFAULT_DISPLAY_WIDTH: u32 = 1280;
19 pub const DEFAULT_DISPLAY_HEIGHT: u32 = 1024;
20 pub const DEFAULT_DPI: u32 = 320;
21 pub const DEFAULT_REFRESH_RATE: u32 = 60;
22 
default_refresh_rate() -> u3223 fn default_refresh_rate() -> u32 {
24     DEFAULT_REFRESH_RATE
25 }
26 
27 /// Trait that the platform-specific type `DisplayMode` needs to implement.
28 pub(crate) trait DisplayModeTrait {
29     /// Returns the initial host window size.
get_window_size(&self) -> (u32, u32)30     fn get_window_size(&self) -> (u32, u32);
31 
32     /// Returns the virtual display size used for creating the display device.
33     ///
34     /// This may be different from the initial host window size since different display backends may
35     /// have different alignment requirements on it.
get_virtual_display_size(&self) -> (u32, u32)36     fn get_virtual_display_size(&self) -> (u32, u32);
37 }
38 
39 impl Default for DisplayMode {
default() -> Self40     fn default() -> Self {
41         Self::Windowed(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT)
42     }
43 }
44 
45 #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromKeyValues)]
46 #[serde(deny_unknown_fields, rename_all = "kebab-case")]
47 pub struct DisplayParameters {
48     #[serde(default)]
49     pub mode: DisplayMode,
50     #[serde(default)]
51     pub hidden: bool,
52     #[serde(default = "default_refresh_rate")]
53     pub refresh_rate: u32,
54     // TODO(b/260101753): `dpi` has to be an `Option` for supporting CLI backward compatibility.
55     // That should be changed once compat fields below are deprecated.
56     pub dpi: Option<(u32, u32)>,
57     // `horizontal-dpi` and `vertical-dpi` are supported for CLI backward compatibility.
58     #[serde(rename = "horizontal-dpi")]
59     pub __horizontal_dpi_compat: Option<u32>,
60     #[serde(rename = "vertical-dpi")]
61     pub __vertical_dpi_compat: Option<u32>,
62 }
63 
64 impl DisplayParameters {
new( mode: DisplayMode, hidden: bool, refresh_rate: u32, horizontal_dpi: u32, vertical_dpi: u32, ) -> Self65     pub fn new(
66         mode: DisplayMode,
67         hidden: bool,
68         refresh_rate: u32,
69         horizontal_dpi: u32,
70         vertical_dpi: u32,
71     ) -> Self {
72         Self {
73             mode,
74             hidden,
75             refresh_rate,
76             dpi: Some((horizontal_dpi, vertical_dpi)),
77             __horizontal_dpi_compat: None,
78             __vertical_dpi_compat: None,
79         }
80     }
81 
default_with_mode(mode: DisplayMode) -> Self82     pub fn default_with_mode(mode: DisplayMode) -> Self {
83         Self::new(mode, false, DEFAULT_REFRESH_RATE, DEFAULT_DPI, DEFAULT_DPI)
84     }
85 
get_window_size(&self) -> (u32, u32)86     pub fn get_window_size(&self) -> (u32, u32) {
87         self.mode.get_window_size()
88     }
89 
get_virtual_display_size(&self) -> (u32, u32)90     pub fn get_virtual_display_size(&self) -> (u32, u32) {
91         self.mode.get_virtual_display_size()
92     }
93 
horizontal_dpi(&self) -> u3294     pub fn horizontal_dpi(&self) -> u32 {
95         self.dpi.expect("'dpi' is None").0
96     }
97 
vertical_dpi(&self) -> u3298     pub fn vertical_dpi(&self) -> u32 {
99         self.dpi.expect("'dpi' is None").1
100     }
101 }
102 
103 impl Default for DisplayParameters {
default() -> Self104     fn default() -> Self {
105         Self::default_with_mode(Default::default())
106     }
107 }
108 
109 #[derive(Serialize, Deserialize, Debug)]
110 pub enum GpuControlCommand {
111     AddDisplays { displays: Vec<DisplayParameters> },
112     ListDisplays,
113     RemoveDisplays { display_ids: Vec<u32> },
114 }
115 
116 #[derive(Serialize, Deserialize, Debug, Clone)]
117 pub enum GpuControlResult {
118     DisplaysUpdated,
119     DisplayList {
120         displays: Map<u32, DisplayParameters>,
121     },
122     TooManyDisplays(usize),
123     NoSuchDisplay {
124         display_id: u32,
125     },
126 }
127 
128 impl Display for GpuControlResult {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result129     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
130         use self::GpuControlResult::*;
131 
132         match self {
133             DisplaysUpdated => write!(f, "displays updated"),
134             DisplayList { displays } => {
135                 let json: serde_json::Value = serde_json::json!({
136                     "displays": displays,
137                 });
138                 let json_pretty =
139                     serde_json::to_string_pretty(&json).map_err(|_| std::fmt::Error)?;
140                 write!(f, "{}", json_pretty)
141             }
142             TooManyDisplays(n) => write!(f, "too_many_displays {}", n),
143             NoSuchDisplay { display_id } => write!(f, "no_such_display {}", display_id),
144         }
145     }
146 }
147 
148 pub enum ModifyGpuError {
149     SocketFailed,
150     UnexpectedResponse(VmResponse),
151     UnknownCommand(String),
152     GpuControl(GpuControlResult),
153 }
154 
155 impl fmt::Display for ModifyGpuError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result156     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157         use self::ModifyGpuError::*;
158 
159         match self {
160             SocketFailed => write!(f, "socket failed"),
161             UnexpectedResponse(r) => write!(f, "unexpected response: {}", r),
162             UnknownCommand(c) => write!(f, "unknown display command: `{}`", c),
163             GpuControl(e) => write!(f, "{}", e),
164         }
165     }
166 }
167 
168 pub type ModifyGpuResult = std::result::Result<GpuControlResult, ModifyGpuError>;
169 
170 impl From<VmResponse> for ModifyGpuResult {
from(response: VmResponse) -> Self171     fn from(response: VmResponse) -> Self {
172         match response {
173             VmResponse::GpuResponse(gpu_response) => Ok(gpu_response),
174             r => Err(ModifyGpuError::UnexpectedResponse(r)),
175         }
176     }
177 }
178 
do_gpu_display_add<T: AsRef<Path> + std::fmt::Debug>( control_socket_path: T, displays: Vec<DisplayParameters>, ) -> ModifyGpuResult179 pub fn do_gpu_display_add<T: AsRef<Path> + std::fmt::Debug>(
180     control_socket_path: T,
181     displays: Vec<DisplayParameters>,
182 ) -> ModifyGpuResult {
183     let request = VmRequest::GpuCommand(GpuControlCommand::AddDisplays { displays });
184     handle_request(&request, control_socket_path)
185         .map_err(|_| ModifyGpuError::SocketFailed)?
186         .into()
187 }
188 
do_gpu_display_list<T: AsRef<Path> + std::fmt::Debug>( control_socket_path: T, ) -> ModifyGpuResult189 pub fn do_gpu_display_list<T: AsRef<Path> + std::fmt::Debug>(
190     control_socket_path: T,
191 ) -> ModifyGpuResult {
192     let request = VmRequest::GpuCommand(GpuControlCommand::ListDisplays);
193     handle_request(&request, control_socket_path)
194         .map_err(|_| ModifyGpuError::SocketFailed)?
195         .into()
196 }
197 
do_gpu_display_remove<T: AsRef<Path> + std::fmt::Debug>( control_socket_path: T, display_ids: Vec<u32>, ) -> ModifyGpuResult198 pub fn do_gpu_display_remove<T: AsRef<Path> + std::fmt::Debug>(
199     control_socket_path: T,
200     display_ids: Vec<u32>,
201 ) -> ModifyGpuResult {
202     let request = VmRequest::GpuCommand(GpuControlCommand::RemoveDisplays { display_ids });
203     handle_request(&request, control_socket_path)
204         .map_err(|_| ModifyGpuError::SocketFailed)?
205         .into()
206 }
207