Skip to content

Commit 41ce7ae

Browse files
ids1024Drakulix
authored andcommitted
Add planes example
This shows information about DRM planes, under the CRTC and connector they are associated with. I've found this useful for trying to understand what's going on with planes vs trying to read `drm_info` output, so it may as well be added here.
1 parent f383da8 commit 41ce7ae

File tree

2 files changed

+160
-3
lines changed

2 files changed

+160
-3
lines changed

examples/planes.rs

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
use drm::control::property::Value;
2+
use std::{collections::HashMap, fs, io};
3+
4+
pub mod utils;
5+
use crate::utils::*;
6+
7+
fn convert_value((type_, value): &(drm::control::property::ValueType, u64)) -> Value<'_> {
8+
type_.convert_value(*value)
9+
}
10+
11+
// 16.16 fixed point
12+
fn convert_value_fixed((type_, value): &(drm::control::property::ValueType, u64)) -> Option<f64> {
13+
let val = type_.convert_value(*value).as_unsigned_range()? as u32;
14+
Some(val as f64 / 0xffff as f64)
15+
}
16+
17+
fn display_plane(
18+
card: &Card,
19+
plane_handle: drm::control::plane::Handle,
20+
plane: drm::control::plane::Info,
21+
) -> io::Result<()> {
22+
let props = card.get_properties(plane_handle)?;
23+
let mut prop_map = HashMap::new();
24+
for (handle, value) in &props {
25+
let info = card.get_property(*handle)?;
26+
let name = info.name().to_str().unwrap().to_owned();
27+
prop_map.insert(name, (info.value_type(), *value));
28+
}
29+
let Value::Enum(Some(type_)) = convert_value(&prop_map["type"]) else {
30+
panic!("failed to convert plane type enum");
31+
};
32+
println!(" Type: {}", type_.name().to_str().unwrap());
33+
println!(
34+
" CRTC_XYWH: ({}, {}) {}x{}",
35+
convert_value(&prop_map["CRTC_X"])
36+
.as_signed_range()
37+
.unwrap(),
38+
convert_value(&prop_map["CRTC_Y"])
39+
.as_signed_range()
40+
.unwrap(),
41+
convert_value(&prop_map["CRTC_W"])
42+
.as_unsigned_range()
43+
.unwrap(),
44+
convert_value(&prop_map["CRTC_H"])
45+
.as_unsigned_range()
46+
.unwrap()
47+
);
48+
println!(
49+
" SRC_XYWH: ({:.1}, {:.1}) {:.1}x{:.1}",
50+
convert_value_fixed(&prop_map["SRC_X"]).unwrap(),
51+
convert_value_fixed(&prop_map["SRC_Y"]).unwrap(),
52+
convert_value_fixed(&prop_map["SRC_W"]).unwrap(),
53+
convert_value_fixed(&prop_map["SRC_H"]).unwrap()
54+
);
55+
if let Some(framebuffer_handle) = plane.framebuffer() {
56+
println!(" {:?}", framebuffer_handle);
57+
let framebuffer = card.get_planar_framebuffer(framebuffer_handle).unwrap();
58+
println!(" Format: {:?}", framebuffer.pixel_format());
59+
if let Some(modifier) = framebuffer.modifier() {
60+
println!(" Modifier: {:?}", modifier);
61+
}
62+
println!(
63+
" Size: {}x{}",
64+
framebuffer.size().0,
65+
framebuffer.size().1
66+
);
67+
68+
println!(" Planes");
69+
for i in 0..4 {
70+
println!(
71+
" Plane {} (offset: {}, pitch: {})",
72+
i,
73+
framebuffer.offsets()[i],
74+
framebuffer.pitches()[i]
75+
);
76+
}
77+
}
78+
Ok(())
79+
}
80+
81+
fn display_card(card: &Card) -> io::Result<()> {
82+
for &cap in capabilities::CLIENT_CAP_ENUMS {
83+
card.set_client_capability(cap, true)?;
84+
}
85+
86+
let resources = card.resource_handles()?;
87+
88+
let mut planes = Vec::new();
89+
for connector_handle in resources.connectors() {
90+
let connector = card.get_connector(*connector_handle, false)?;
91+
if connector.state() != drm::control::connector::State::Connected {
92+
continue;
93+
}
94+
95+
println!(" {:?}", connector_handle);
96+
println!(
97+
" {:?}{}",
98+
connector.interface(),
99+
connector.interface_id()
100+
);
101+
if let Some(encoder_handle) = connector.current_encoder() {
102+
let encoder = card.get_encoder(encoder_handle)?;
103+
println!(" {:?}", encoder_handle);
104+
println!(" Kind: {:?}", encoder.kind());
105+
if let Some(crtc_handle) = encoder.crtc() {
106+
println!(" {:?}", crtc_handle);
107+
let crtc = card.get_crtc(crtc_handle)?;
108+
if let Some(mode) = crtc.mode() {
109+
println!(" {:?}", mode);
110+
}
111+
for plane_handle in card.plane_handles()? {
112+
let plane = card.get_plane(plane_handle)?;
113+
if plane.crtc() != Some(crtc_handle) {
114+
continue;
115+
}
116+
planes.push(plane_handle);
117+
println!(" {:?}", plane_handle);
118+
display_plane(card, plane_handle, plane)?;
119+
}
120+
}
121+
}
122+
}
123+
124+
println!("Planes not associated with connector");
125+
for plane_handle in card.plane_handles()? {
126+
if !planes.contains(&plane_handle) {
127+
let plane = card.get_plane(plane_handle)?;
128+
println!(" {:?}", plane_handle);
129+
display_plane(card, plane_handle, plane)?;
130+
}
131+
}
132+
133+
Ok(())
134+
}
135+
136+
fn main() -> io::Result<()> {
137+
for i in fs::read_dir("/dev/dri")? {
138+
let i = i?;
139+
if i.file_name().to_str().unwrap().starts_with("card") {
140+
if let Ok(card) = Card::open(i.path().to_str().unwrap()) {
141+
let driver = card.get_driver()?;
142+
println!(
143+
"{} ({}, {}, version {}.{}.{})",
144+
i.path().display(),
145+
driver.name.to_str().unwrap(),
146+
driver.desc.to_str().unwrap(),
147+
driver.version.0,
148+
driver.version.1,
149+
driver.version.2
150+
);
151+
display_card(&card)?;
152+
}
153+
}
154+
}
155+
Ok(())
156+
}

examples/utils/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
pub use drm::control::Device as ControlDevice;
44
pub use drm::Device;
5+
use std::io;
56

67
#[derive(Debug)]
78
/// A simple wrapper for a device node.
@@ -21,15 +22,15 @@ impl ControlDevice for Card {}
2122

2223
/// Simple helper methods for opening a `Card`.
2324
impl Card {
24-
pub fn open(path: &str) -> Self {
25+
pub fn open(path: &str) -> io::Result<Self> {
2526
let mut options = std::fs::OpenOptions::new();
2627
options.read(true);
2728
options.write(true);
28-
Card(options.open(path).unwrap())
29+
Ok(Card(options.open(path)?))
2930
}
3031

3132
pub fn open_global() -> Self {
32-
Self::open("/dev/dri/card0")
33+
Self::open("/dev/dri/card0").unwrap()
3334
}
3435
}
3536

0 commit comments

Comments
 (0)