control-center: add GPUs pane
This commit is contained in:
parent
d328655f8b
commit
db06d719dd
7 changed files with 170 additions and 11 deletions
|
|
@ -588,7 +588,6 @@ pub trait BackendDrmDevice {
|
||||||
fn set_flip_margin(&self, margin: u64) {
|
fn set_flip_margin(&self, margin: u64) {
|
||||||
let _ = margin;
|
let _ = margin;
|
||||||
}
|
}
|
||||||
#[expect(dead_code)]
|
|
||||||
fn flip_margin(&self) -> Option<u64> {
|
fn flip_margin(&self) -> Option<u64> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -951,8 +951,10 @@ impl ConfigProxyHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_set_flip_margin(&self, device: DrmDevice, margin: Duration) -> Result<(), CphError> {
|
fn handle_set_flip_margin(&self, device: DrmDevice, margin: Duration) -> Result<(), CphError> {
|
||||||
self.get_drm_device(device)?
|
self.get_drm_device(device)?.set_flip_margin(
|
||||||
.set_flip_margin(margin.as_nanos().try_into().unwrap_or(u64::MAX));
|
&self.state,
|
||||||
|
margin.as_nanos().try_into().unwrap_or(u64::MAX),
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -987,7 +989,7 @@ impl ConfigProxyHandler {
|
||||||
match device {
|
match device {
|
||||||
Some(dev) => self
|
Some(dev) => self
|
||||||
.get_drm_device(dev)?
|
.get_drm_device(dev)?
|
||||||
.set_direct_scanout_enabled(enabled),
|
.set_direct_scanout_enabled(&self.state, enabled),
|
||||||
_ => self.state.direct_scanout_enabled.set(enabled),
|
_ => self.state.direct_scanout_enabled.set(enabled),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
control_center::{
|
control_center::{
|
||||||
cc_color_management::ColorManagementPane, cc_compositor::CompositorPane,
|
cc_color_management::ColorManagementPane, cc_compositor::CompositorPane,
|
||||||
cc_idle::IdlePane, cc_outputs::OutputsPane, cc_xwayland::XwaylandPane,
|
cc_gpus::GpusPane, cc_idle::IdlePane, cc_outputs::OutputsPane,
|
||||||
|
cc_xwayland::XwaylandPane,
|
||||||
},
|
},
|
||||||
egui_adapter::egui_platform::{
|
egui_adapter::egui_platform::{
|
||||||
EggError, EggWindow, EggWindowOwner,
|
EggError, EggWindow, EggWindowOwner,
|
||||||
|
|
@ -35,6 +36,7 @@ use {
|
||||||
|
|
||||||
mod cc_color_management;
|
mod cc_color_management;
|
||||||
mod cc_compositor;
|
mod cc_compositor;
|
||||||
|
mod cc_gpus;
|
||||||
mod cc_idle;
|
mod cc_idle;
|
||||||
mod cc_outputs;
|
mod cc_outputs;
|
||||||
mod cc_sidebar;
|
mod cc_sidebar;
|
||||||
|
|
@ -76,6 +78,7 @@ bitflags! {
|
||||||
CCI_COLOR_MANAGEMENT,
|
CCI_COLOR_MANAGEMENT,
|
||||||
CCI_XWAYLAND,
|
CCI_XWAYLAND,
|
||||||
CCI_OUTPUTS,
|
CCI_OUTPUTS,
|
||||||
|
CCI_GPUS,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ControlCenter {
|
pub struct ControlCenter {
|
||||||
|
|
@ -121,6 +124,7 @@ enum PaneType {
|
||||||
ColorManagement(ColorManagementPane),
|
ColorManagement(ColorManagementPane),
|
||||||
Xwayland(XwaylandPane),
|
Xwayland(XwaylandPane),
|
||||||
Outputs(Box<OutputsPane>),
|
Outputs(Box<OutputsPane>),
|
||||||
|
GPUs(GpusPane),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CcBehavior<'a> {
|
struct CcBehavior<'a> {
|
||||||
|
|
@ -144,6 +148,7 @@ impl Pane {
|
||||||
PaneType::ColorManagement(v) => v.title(res),
|
PaneType::ColorManagement(v) => v.title(res),
|
||||||
PaneType::Xwayland(v) => v.title(res),
|
PaneType::Xwayland(v) => v.title(res),
|
||||||
PaneType::Outputs(v) => v.title(res),
|
PaneType::Outputs(v) => v.title(res),
|
||||||
|
PaneType::GPUs(v) => v.title(res),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,6 +159,7 @@ impl Pane {
|
||||||
PaneType::ColorManagement(p) => p.show(ui),
|
PaneType::ColorManagement(p) => p.show(ui),
|
||||||
PaneType::Xwayland(p) => p.show(behavior, ui),
|
PaneType::Xwayland(p) => p.show(behavior, ui),
|
||||||
PaneType::Outputs(p) => p.show(&mut self.ps, ui),
|
PaneType::Outputs(p) => p.show(&mut self.ps, ui),
|
||||||
|
PaneType::GPUs(p) => p.show(ui),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -166,6 +172,7 @@ impl PaneType {
|
||||||
PaneType::ColorManagement(_) => CCI_COLOR_MANAGEMENT,
|
PaneType::ColorManagement(_) => CCI_COLOR_MANAGEMENT,
|
||||||
PaneType::Xwayland(_) => CCI_XWAYLAND,
|
PaneType::Xwayland(_) => CCI_XWAYLAND,
|
||||||
PaneType::Outputs(_) => CCI_OUTPUTS,
|
PaneType::Outputs(_) => CCI_OUTPUTS,
|
||||||
|
PaneType::GPUs(_) => CCI_GPUS,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
146
src/control_center/cc_gpus.rs
Normal file
146
src/control_center/cc_gpus.rs
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
control_center::{
|
||||||
|
ControlCenterInner, GridExt, bool, combo_box, grid, grid_label, label, row,
|
||||||
|
},
|
||||||
|
egui_adapter::egui_platform::icons::{ICON_ADD, ICON_REMOVE},
|
||||||
|
state::{DrmDevData, State},
|
||||||
|
},
|
||||||
|
egui::{Checkbox, CollapsingHeader, DragValue, TextFormat, Ui, Widget, text::LayoutJob},
|
||||||
|
std::rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct GpusPane {
|
||||||
|
state: Rc<State>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ControlCenterInner {
|
||||||
|
pub fn create_gpus_pane(self: &Rc<Self>) -> GpusPane {
|
||||||
|
GpusPane {
|
||||||
|
state: self.state.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GpusPane {
|
||||||
|
pub fn title(&self, res: &mut String) {
|
||||||
|
res.push_str("GPUs");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn show(&mut self, ui: &mut Ui) {
|
||||||
|
let devs = self.state.drm_devs.lock();
|
||||||
|
let mut devs: Vec<_> = devs.iter().collect();
|
||||||
|
devs.sort_by_key(|d| d.0);
|
||||||
|
for dev in devs {
|
||||||
|
self.show_dev(ui, dev.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_dev(&self, ui: &mut Ui, dev: &DrmDevData) {
|
||||||
|
let title_buf;
|
||||||
|
let title = match dev.devnode.as_deref() {
|
||||||
|
Some(t) => t,
|
||||||
|
_ => {
|
||||||
|
let dev_t = dev.dev.dev_t();
|
||||||
|
title_buf = format!("{}:{}", uapi::major(dev_t), uapi::minor(dev_t));
|
||||||
|
&title_buf
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut layout_job = LayoutJob::default();
|
||||||
|
layout_job.append(
|
||||||
|
title,
|
||||||
|
0.0,
|
||||||
|
TextFormat {
|
||||||
|
color: ui.style().visuals.widgets.active.text_color(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if let Some(model) = &dev.model {
|
||||||
|
layout_job.append(
|
||||||
|
model,
|
||||||
|
10.0,
|
||||||
|
TextFormat {
|
||||||
|
color: ui.style().visuals.widgets.inactive.text_color(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ui.collapsing(layout_job, |ui| {
|
||||||
|
grid(ui, ("settings", dev.dev.id()), |ui| {
|
||||||
|
macro_rules! string {
|
||||||
|
($field:ident, $name:expr) => {
|
||||||
|
if let Some(v) = &dev.$field {
|
||||||
|
label(ui, $name, v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
string!(vendor, "Vendor");
|
||||||
|
string!(model, "Model");
|
||||||
|
string!(devnode, "Devnode");
|
||||||
|
string!(syspath, "Syspath");
|
||||||
|
if let Some(v) = dev.pci_id {
|
||||||
|
label(ui, "PCI ID", format!("{:x}:{:x}", v.vendor, v.model));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let v = dev.dev.dev_t();
|
||||||
|
label(ui, "Dev", format!("{}:{}", uapi::major(v), uapi::minor(v)));
|
||||||
|
}
|
||||||
|
combo_box(ui, "API", dev.dev.gtx_api(), |v| dev.dev.set_gfx_api(v));
|
||||||
|
row(ui, "Primary Device", |ui| {
|
||||||
|
let mut v = dev.dev.is_render_device();
|
||||||
|
let old = v;
|
||||||
|
ui.add_enabled(!v, Checkbox::without_text(&mut v));
|
||||||
|
if v != old {
|
||||||
|
dev.dev.make_render_device();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
bool(
|
||||||
|
ui,
|
||||||
|
"Direct Scanout",
|
||||||
|
dev.dev.direct_scanout_enabled(),
|
||||||
|
|v| dev.set_direct_scanout_enabled(&self.state, v),
|
||||||
|
);
|
||||||
|
if let Some(mut v) = dev.dev.flip_margin() {
|
||||||
|
let ui = &mut *ui.row();
|
||||||
|
grid_label(ui, "Flip Margin");
|
||||||
|
let old = v;
|
||||||
|
let denom = 1_000_000.0;
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
let mut s = v as f64 / denom;
|
||||||
|
let res = DragValue::new(&mut s)
|
||||||
|
.range(0.0..=50.0)
|
||||||
|
.speed(0.1)
|
||||||
|
.fixed_decimals(1)
|
||||||
|
.ui(ui);
|
||||||
|
if res.changed() {
|
||||||
|
v = (s * denom) as u64;
|
||||||
|
}
|
||||||
|
if ui.button(ICON_REMOVE).clicked() {
|
||||||
|
v = v.saturating_sub(100_000);
|
||||||
|
}
|
||||||
|
if ui.button(ICON_ADD).clicked() {
|
||||||
|
v += 100_000;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if old != v {
|
||||||
|
dev.set_flip_margin(&self.state, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
CollapsingHeader::new("Connectors")
|
||||||
|
.default_open(true)
|
||||||
|
.show(ui, |ui| {
|
||||||
|
let mut cs: Vec<_> = dev
|
||||||
|
.connectors
|
||||||
|
.lock()
|
||||||
|
.values()
|
||||||
|
.map(|v| v.connector.kernel_id().to_string())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
cs.sort();
|
||||||
|
for c in cs {
|
||||||
|
ui.label(c);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ enum PaneName {
|
||||||
ColorManagement,
|
ColorManagement,
|
||||||
Xwayland,
|
Xwayland,
|
||||||
Outputs,
|
Outputs,
|
||||||
|
GPUs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PaneName {
|
impl PaneName {
|
||||||
|
|
@ -23,6 +24,7 @@ impl PaneName {
|
||||||
PaneName::ColorManagement => "Color Management",
|
PaneName::ColorManagement => "Color Management",
|
||||||
PaneName::Xwayland => "Xwayland",
|
PaneName::Xwayland => "Xwayland",
|
||||||
PaneName::Outputs => "Outputs",
|
PaneName::Outputs => "Outputs",
|
||||||
|
PaneName::GPUs => "GPUs",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -60,6 +62,7 @@ impl ControlCenterInner {
|
||||||
PaneName::Outputs => {
|
PaneName::Outputs => {
|
||||||
PaneType::Outputs(Box::new(self.create_outputs_pane()))
|
PaneType::Outputs(Box::new(self.create_outputs_pane()))
|
||||||
}
|
}
|
||||||
|
PaneName::GPUs => PaneType::GPUs(self.create_gpus_pane()),
|
||||||
};
|
};
|
||||||
self.open(tree, ty);
|
self.open(tree, ty);
|
||||||
ui.ctx().request_repaint();
|
ui.ctx().request_repaint();
|
||||||
|
|
|
||||||
|
|
@ -350,7 +350,7 @@ impl JayRandrRequestHandler for JayRandr {
|
||||||
let Some(dev) = self.get_device(req.dev) else {
|
let Some(dev) = self.get_device(req.dev) else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
dev.set_direct_scanout_enabled(req.enabled != 0);
|
dev.set_direct_scanout_enabled(&self.state, req.enabled != 0);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -493,7 +493,7 @@ impl JayRandrRequestHandler for JayRandr {
|
||||||
let Some(dev) = self.get_device(req.dev) else {
|
let Some(dev) = self.get_device(req.dev) else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
dev.set_flip_margin(req.margin_ns);
|
dev.set_flip_margin(&self.state, req.margin_ns);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
src/state.rs
10
src/state.rs
|
|
@ -17,7 +17,7 @@ use {
|
||||||
compositor::{LIBEI_SOCKET, LogLevel},
|
compositor::{LIBEI_SOCKET, LogLevel},
|
||||||
config::ConfigProxy,
|
config::ConfigProxy,
|
||||||
control_center::{
|
control_center::{
|
||||||
CCI_COLOR_MANAGEMENT, CCI_COMPOSITOR, CCI_IDLE, CCI_OUTPUTS, CCI_XWAYLAND,
|
CCI_COLOR_MANAGEMENT, CCI_COMPOSITOR, CCI_GPUS, CCI_IDLE, CCI_OUTPUTS, CCI_XWAYLAND,
|
||||||
ControlCenters,
|
ControlCenters,
|
||||||
},
|
},
|
||||||
copy_device::CopyDeviceRegistry,
|
copy_device::CopyDeviceRegistry,
|
||||||
|
|
@ -549,12 +549,14 @@ impl DrmDevData {
|
||||||
self.dev.clone().make_render_device();
|
self.dev.clone().make_render_device();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_direct_scanout_enabled(&self, enabled: bool) {
|
pub fn set_direct_scanout_enabled(&self, state: &State, enabled: bool) {
|
||||||
self.dev.set_direct_scanout_enabled(enabled);
|
self.dev.set_direct_scanout_enabled(enabled);
|
||||||
|
state.trigger_cci(CCI_GPUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_flip_margin(&self, margin: u64) {
|
pub fn set_flip_margin(&self, state: &State, margin: u64) {
|
||||||
self.dev.set_flip_margin(margin);
|
self.dev.set_flip_margin(margin);
|
||||||
|
state.trigger_cci(CCI_GPUS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -778,7 +780,7 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.expose_new_singletons();
|
self.expose_new_singletons();
|
||||||
self.trigger_cci(CCI_COLOR_MANAGEMENT);
|
self.trigger_cci(CCI_COLOR_MANAGEMENT | CCI_GPUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload_cursors(&self) {
|
fn reload_cursors(&self) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue