debug: Add image support and gpu vendor logos
This commit is contained in:
parent
cd5c185440
commit
1de4b97bca
11 changed files with 541 additions and 71 deletions
|
|
@ -504,22 +504,32 @@ impl State {
|
|||
let outputs = device.enumerate_surfaces()?.added; // There are no removed outputs on newly added devices
|
||||
let mut wl_outputs = Vec::new();
|
||||
let mut w = self.common.shell.global_space().size.w;
|
||||
for (crtc, conn) in outputs {
|
||||
match device.setup_surface(crtc, conn, (w, 0)) {
|
||||
Ok(output) => {
|
||||
w += output
|
||||
.user_data()
|
||||
.get::<RefCell<OutputConfig>>()
|
||||
.unwrap()
|
||||
.borrow()
|
||||
.mode_size()
|
||||
.w;
|
||||
wl_outputs.push(output);
|
||||
}
|
||||
Err(err) => slog_scope::warn!("Failed to initialize output: {}", err),
|
||||
};
|
||||
{
|
||||
let backend = self.backend.kms();
|
||||
for (crtc, conn) in outputs {
|
||||
let mut renderer = match backend.api.renderer(&render_node, &render_node) {
|
||||
Ok(renderer) => renderer,
|
||||
Err(err) => {
|
||||
slog_scope::warn!("Failed to initialize output: {}", err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
match device.setup_surface(crtc, conn, (w, 0), &mut renderer) {
|
||||
Ok(output) => {
|
||||
w += output
|
||||
.user_data()
|
||||
.get::<RefCell<OutputConfig>>()
|
||||
.unwrap()
|
||||
.borrow()
|
||||
.mode_size()
|
||||
.w;
|
||||
wl_outputs.push(output);
|
||||
}
|
||||
Err(err) => slog_scope::warn!("Failed to initialize output: {}", err),
|
||||
};
|
||||
}
|
||||
backend.devices.insert(drm_node, device);
|
||||
}
|
||||
self.backend.kms().devices.insert(drm_node, device);
|
||||
|
||||
self.common
|
||||
.output_configuration_state
|
||||
|
|
@ -542,32 +552,45 @@ impl State {
|
|||
let drm_node = DrmNode::from_dev_id(dev)?;
|
||||
let mut outputs_removed = Vec::new();
|
||||
let mut outputs_added = Vec::new();
|
||||
if let Some(device) = self.backend.kms().devices.get_mut(&drm_node) {
|
||||
let changes = device.enumerate_surfaces()?;
|
||||
let mut w = self.common.shell.global_space().size.w;
|
||||
for crtc in changes.removed {
|
||||
if let Some(surface) = device.surfaces.remove(&crtc) {
|
||||
if let Some(token) = surface.render_timer_token {
|
||||
self.common.event_loop_handle.remove(token);
|
||||
{
|
||||
let backend = self.backend.kms();
|
||||
if let Some(device) = backend.devices.get_mut(&drm_node) {
|
||||
let changes = device.enumerate_surfaces()?;
|
||||
let mut w = self.common.shell.global_space().size.w;
|
||||
for crtc in changes.removed {
|
||||
if let Some(surface) = device.surfaces.remove(&crtc) {
|
||||
if let Some(token) = surface.render_timer_token {
|
||||
self.common.event_loop_handle.remove(token);
|
||||
}
|
||||
w -= surface.output.current_mode().map(|m| m.size.w).unwrap_or(0);
|
||||
outputs_removed.push(surface.output.clone());
|
||||
}
|
||||
w -= surface.output.current_mode().map(|m| m.size.w).unwrap_or(0);
|
||||
outputs_removed.push(surface.output.clone());
|
||||
}
|
||||
}
|
||||
for (crtc, conn) in changes.added {
|
||||
match device.setup_surface(crtc, conn, (w, 0)) {
|
||||
Ok(output) => {
|
||||
w += output
|
||||
.user_data()
|
||||
.get::<RefCell<OutputConfig>>()
|
||||
.unwrap()
|
||||
.borrow()
|
||||
.mode_size()
|
||||
.w;
|
||||
outputs_added.push(output);
|
||||
}
|
||||
Err(err) => slog_scope::warn!("Failed to initialize output: {}", err),
|
||||
};
|
||||
for (crtc, conn) in changes.added {
|
||||
let mut renderer = match backend
|
||||
.api
|
||||
.renderer(&device.render_node, &device.render_node)
|
||||
{
|
||||
Ok(renderer) => renderer,
|
||||
Err(err) => {
|
||||
slog_scope::warn!("Failed to initialize output: {}", err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
match device.setup_surface(crtc, conn, (w, 0), &mut renderer) {
|
||||
Ok(output) => {
|
||||
w += output
|
||||
.user_data()
|
||||
.get::<RefCell<OutputConfig>>()
|
||||
.unwrap()
|
||||
.borrow()
|
||||
.mode_size()
|
||||
.w;
|
||||
outputs_added.push(output);
|
||||
}
|
||||
Err(err) => slog_scope::warn!("Failed to initialize output: {}", err),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -671,6 +694,7 @@ impl Device {
|
|||
crtc: crtc::Handle,
|
||||
conn: connector::Handle,
|
||||
position: (i32, i32),
|
||||
renderer: &mut GlMultiRenderer<'_>,
|
||||
) -> Result<Output> {
|
||||
let drm = &mut *self.drm.as_source_mut();
|
||||
let crtc_info = drm.get_crtc(crtc)?;
|
||||
|
|
@ -745,7 +769,7 @@ impl Device {
|
|||
dirty: false,
|
||||
render_timer_token: None,
|
||||
#[cfg(feature = "debug")]
|
||||
fps: Fps::default(),
|
||||
fps: Fps::new(renderer.as_mut()),
|
||||
};
|
||||
self.surfaces.insert(crtc, data);
|
||||
|
||||
|
|
|
|||
|
|
@ -237,6 +237,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
impl<R> From<TextureRenderElement<Gles2Texture>> for CosmicElement<R>
|
||||
where
|
||||
R: Renderer + ImportAll + AsGlowRenderer,
|
||||
|
|
|
|||
|
|
@ -221,13 +221,16 @@ pub fn init_backend(
|
|||
.map_err(|_| anyhow::anyhow!("Failed to init eventloop timer for winit"))?;
|
||||
event_ping.ping();
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
let fps = Fps::new(backend.renderer());
|
||||
|
||||
state.backend = BackendData::Winit(WinitState {
|
||||
backend,
|
||||
output: output.clone(),
|
||||
damage_tracker: DamageTrackedRenderer::from_output(&output),
|
||||
screencopy: Vec::new(),
|
||||
#[cfg(feature = "debug")]
|
||||
fps: Fps::default(),
|
||||
fps,
|
||||
});
|
||||
state
|
||||
.common
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ impl X11State {
|
|||
pending: true,
|
||||
screencopy: Vec::new(),
|
||||
#[cfg(feature = "debug")]
|
||||
fps: Fps::default(),
|
||||
fps: Fps::new(&mut self.renderer),
|
||||
});
|
||||
|
||||
// schedule first render
|
||||
|
|
|
|||
50
src/debug.rs
50
src/debug.rs
|
|
@ -1,7 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::state::{Common, Fps};
|
||||
use egui::Color32;
|
||||
use egui::{Color32, Vec2};
|
||||
use smithay::{
|
||||
backend::{
|
||||
drm::DrmNode,
|
||||
|
|
@ -29,7 +31,7 @@ pub fn fps_ui(
|
|||
area: Rectangle<i32, Logical>,
|
||||
scale: f64,
|
||||
) -> Result<TextureRenderElement<Gles2Texture>, Gles2Error> {
|
||||
use egui::widgets::plot::{Bar, BarChart, HLine, Legend, Plot};
|
||||
use egui::widgets::plot::{Bar, BarChart, Legend, Plot};
|
||||
|
||||
let (max, min, avg, avg_fps) = (
|
||||
fps.max_frametime().as_secs_f64(),
|
||||
|
|
@ -84,6 +86,33 @@ pub fn fps_ui(
|
|||
})
|
||||
.unzip();
|
||||
|
||||
let vendors = HashMap::from([
|
||||
(
|
||||
"0x10de",
|
||||
fps.state
|
||||
.with_image(renderer, "nvidia", |image, ctx| {
|
||||
(image.texture_id(ctx), image.size_vec2())
|
||||
})
|
||||
.expect("Logo images not loaded?"),
|
||||
),
|
||||
(
|
||||
"0x1002",
|
||||
fps.state
|
||||
.with_image(renderer, "amd", |image, ctx| {
|
||||
(image.texture_id(ctx), image.size_vec2())
|
||||
})
|
||||
.expect("Logo images not loaded?"),
|
||||
),
|
||||
(
|
||||
"0x8086",
|
||||
fps.state
|
||||
.with_image(renderer, "intel", |image, ctx| {
|
||||
(image.texture_id(ctx), image.size_vec2())
|
||||
})
|
||||
.expect("Logo images not loaded?"),
|
||||
),
|
||||
]);
|
||||
|
||||
fps.state.render(
|
||||
|ctx| {
|
||||
egui::Area::new("main")
|
||||
|
|
@ -104,7 +133,22 @@ pub fn fps_ui(
|
|||
ui.separator();
|
||||
|
||||
if let Some(gpu) = gpu {
|
||||
ui.label(egui::RichText::new(format!("renderD{}", gpu.minor())).code());
|
||||
ui.horizontal(|ui| {
|
||||
let resp = ui.label(
|
||||
egui::RichText::new(format!("renderD{}", gpu.minor())).code(),
|
||||
);
|
||||
if let Ok(vendor) = std::fs::read_to_string(format!(
|
||||
"/sys/class/drm/renderD{}/device/vendor",
|
||||
gpu.minor()
|
||||
)) {
|
||||
if let Some((texture_id, mut size)) = vendors.get(vendor.trim())
|
||||
{
|
||||
let factor = resp.rect.height() / size.y;
|
||||
size = Vec2::from([size.x * factor, resp.rect.height()]);
|
||||
ui.image(*texture_id, size);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
ui.label(egui::RichText::new(format!("FPS: {:>7.3}", avg_fps)).heading());
|
||||
ui.label("Frame Times:");
|
||||
|
|
|
|||
42
src/state.rs
42
src/state.rs
|
|
@ -14,6 +14,8 @@ use crate::{
|
|||
},
|
||||
};
|
||||
use cosmic_protocols::screencopy::v1::server::zcosmic_screencopy_manager_v1::CursorMode;
|
||||
#[cfg(feature = "debug")]
|
||||
use smithay::backend::renderer::glow::GlowRenderer;
|
||||
use smithay::{
|
||||
backend::{
|
||||
drm::DrmNode,
|
||||
|
|
@ -465,6 +467,7 @@ pub struct Frame {
|
|||
pub duration_displayed: Duration,
|
||||
}
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
impl Frame {
|
||||
fn frame_time(&self) -> Duration {
|
||||
self.duration_elements
|
||||
|
|
@ -480,6 +483,7 @@ impl Frame {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
impl From<PendingFrame> for Frame {
|
||||
fn from(pending: PendingFrame) -> Self {
|
||||
Frame {
|
||||
|
|
@ -541,7 +545,7 @@ impl Fps {
|
|||
);
|
||||
|
||||
self.frames.push_back(frame.into());
|
||||
if self.frames.len() > Fps::WINDOW_SIZE {
|
||||
while self.frames.len() > Fps::WINDOW_SIZE {
|
||||
self.frames.pop_front();
|
||||
}
|
||||
}
|
||||
|
|
@ -601,18 +605,34 @@ impl Fps {
|
|||
}
|
||||
}
|
||||
|
||||
static INTEL_LOGO: &'static [u8] = include_bytes!("../resources/icons/intel.svg");
|
||||
static AMD_LOGO: &'static [u8] = include_bytes!("../resources/icons/amd.svg");
|
||||
static NVIDIA_LOGO: &'static [u8] = include_bytes!("../resources/icons/nvidia.svg");
|
||||
|
||||
#[cfg(feature = "debug")]
|
||||
impl Default for Fps {
|
||||
fn default() -> Fps {
|
||||
impl Fps {
|
||||
pub fn new(renderer: &mut GlowRenderer) -> Fps {
|
||||
let state = {
|
||||
let state =
|
||||
smithay_egui::EguiState::new(Rectangle::from_loc_and_size((0, 0), (400, 800)));
|
||||
let mut visuals: egui::style::Visuals = Default::default();
|
||||
visuals.window_shadow.extrusion = 0.0;
|
||||
state.context().set_visuals(visuals);
|
||||
state
|
||||
};
|
||||
|
||||
state
|
||||
.load_svg(renderer, String::from("intel"), INTEL_LOGO)
|
||||
.unwrap();
|
||||
state
|
||||
.load_svg(renderer, String::from("amd"), AMD_LOGO)
|
||||
.unwrap();
|
||||
state
|
||||
.load_svg(renderer, String::from("nvidia"), NVIDIA_LOGO)
|
||||
.unwrap();
|
||||
|
||||
Fps {
|
||||
state: {
|
||||
let state =
|
||||
smithay_egui::EguiState::new(Rectangle::from_loc_and_size((0, 0), (400, 800)));
|
||||
let mut visuals: egui::style::Visuals = Default::default();
|
||||
visuals.window_shadow.extrusion = 0.0;
|
||||
state.context().set_visuals(visuals);
|
||||
state
|
||||
},
|
||||
state,
|
||||
pending_frame: None,
|
||||
frames: VecDeque::with_capacity(Fps::WINDOW_SIZE + 1),
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue