Skip to content

Commit

Permalink
Merge pull request #169 from linkmauve/fewer-getproperty
Browse files Browse the repository at this point in the history
Reduce the number of get_property ioctls called
  • Loading branch information
Drakulix authored Sep 25, 2023
2 parents 088030d + 81e8d1c commit 61a7415
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 47 deletions.
23 changes: 11 additions & 12 deletions drm-ffi/src/mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,26 +554,25 @@ pub fn get_property(
mut values: Option<&mut Vec<u64>>,
mut enums: Option<&mut Vec<drm_mode_property_enum>>,
) -> Result<drm_mode_get_property, Error> {
let mut sizes = drm_mode_get_property {
let mut prop = drm_mode_get_property {
prop_id,
..Default::default()
};

unsafe {
ioctl::mode::get_property(fd, &mut sizes)?;
ioctl::mode::get_property(fd, &mut prop)?;
}

map_reserve!(values, sizes.count_values as usize);
map_reserve!(enums, sizes.count_enum_blobs as usize);
// There is no need to call get_property() twice if there is nothing else to retrieve.
if prop.count_values == 0 && prop.count_enum_blobs == 0 {
return Ok(prop);
}

let mut prop = drm_mode_get_property {
prop_id,
values_ptr: map_ptr!(&values),
enum_blob_ptr: map_ptr!(&enums),
count_values: map_len!(&values),
count_enum_blobs: map_len!(&enums),
..Default::default()
};
map_reserve!(values, prop.count_values as usize);
map_reserve!(enums, prop.count_enum_blobs as usize);

prop.values_ptr = map_ptr!(&values);
prop.enum_blob_ptr = map_ptr!(&enums);

unsafe {
ioctl::mode::get_property(fd, &mut prop)?;
Expand Down
64 changes: 29 additions & 35 deletions examples/atomic_modeset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,8 @@ use drm::Device as BasicDevice;

use drm::buffer::DrmFourcc;

use drm::control::ResourceHandle;
use drm::control::{self, atomic, connector, crtc, property, AtomicCommitFlags};

fn find_prop_id<T: ResourceHandle>(
card: &Card,
handle: T,
name: &'static str,
) -> Option<property::Handle> {
let props = card
.get_properties(handle)
.expect("Could not get props of connector");
let (ids, _vals) = props.as_props_and_values();
ids.iter()
.find(|&id| {
let info = card.get_property(*id).unwrap();
info.name().to_str().map(|x| x == name).unwrap_or(false)
})
.cloned()
}

pub fn main() {
let card = Card::open_global();

Expand Down Expand Up @@ -124,73 +106,85 @@ pub fn main() {
println!("{:#?}", db);
println!("{:#?}", plane);

let con_props = card
.get_properties(con.handle())
.expect("Could not get props of connector")
.as_hashmap(&card)
.expect("Could not get a prop from connector");
let crtc_props = card
.get_properties(crtc.handle())
.expect("Could not get props of crtc")
.as_hashmap(&card)
.expect("Could not get a prop from crtc");
let plane_props = card
.get_properties(plane)
.expect("Could not get props of plane")
.as_hashmap(&card)
.expect("Could not get a prop from plane");

let mut atomic_req = atomic::AtomicModeReq::new();
atomic_req.add_property(
con.handle(),
find_prop_id(&card, con.handle(), "CRTC_ID").expect("Could not get CRTC_ID"),
con_props["CRTC_ID"].handle(),
property::Value::CRTC(Some(crtc.handle())),
);
let blob = card
.create_property_blob(&mode)
.expect("Failed to create blob");
atomic_req.add_property(crtc.handle(), crtc_props["MODE_ID"].handle(), blob);
atomic_req.add_property(
crtc.handle(),
find_prop_id(&card, crtc.handle(), "MODE_ID").expect("Could not get MODE_ID"),
blob,
);
atomic_req.add_property(
crtc.handle(),
find_prop_id(&card, crtc.handle(), "ACTIVE").expect("Could not get ACTIVE"),
crtc_props["ACTIVE"].handle(),
property::Value::Boolean(true),
);
atomic_req.add_property(
plane,
find_prop_id(&card, plane, "FB_ID").expect("Could not get FB_ID"),
plane_props["FB_ID"].handle(),
property::Value::Framebuffer(Some(fb)),
);
atomic_req.add_property(
plane,
find_prop_id(&card, plane, "CRTC_ID").expect("Could not get CRTC_ID"),
plane_props["CRTC_ID"].handle(),
property::Value::CRTC(Some(crtc.handle())),
);
atomic_req.add_property(
plane,
find_prop_id(&card, plane, "SRC_X").expect("Could not get SRC_X"),
plane_props["SRC_X"].handle(),
property::Value::UnsignedRange(0),
);
atomic_req.add_property(
plane,
find_prop_id(&card, plane, "SRC_Y").expect("Could not get SRC_Y"),
plane_props["SRC_Y"].handle(),
property::Value::UnsignedRange(0),
);
atomic_req.add_property(
plane,
find_prop_id(&card, plane, "SRC_W").expect("Could not get SRC_W"),
plane_props["SRC_W"].handle(),
property::Value::UnsignedRange((mode.size().0 as u64) << 16),
);
atomic_req.add_property(
plane,
find_prop_id(&card, plane, "SRC_H").expect("Could not get SRC_H"),
plane_props["SRC_H"].handle(),
property::Value::UnsignedRange((mode.size().1 as u64) << 16),
);
atomic_req.add_property(
plane,
find_prop_id(&card, plane, "CRTC_X").expect("Could not get CRTC_X"),
plane_props["CRTC_X"].handle(),
property::Value::SignedRange(0),
);
atomic_req.add_property(
plane,
find_prop_id(&card, plane, "CRTC_Y").expect("Could not get CRTC_Y"),
plane_props["CRTC_Y"].handle(),
property::Value::SignedRange(0),
);
atomic_req.add_property(
plane,
find_prop_id(&card, plane, "CRTC_W").expect("Could not get CRTC_W"),
plane_props["CRTC_W"].handle(),
property::Value::UnsignedRange(mode.size().0 as u64),
);
atomic_req.add_property(
plane,
find_prop_id(&card, plane, "CRTC_H").expect("Could not get CRTC_H"),
plane_props["CRTC_H"].handle(),
property::Value::UnsignedRange(mode.size().1 as u64),
);

Expand Down
15 changes: 15 additions & 0 deletions src/control/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use buffer;

use super::util::*;

use std::collections::HashMap;
use std::convert::TryFrom;
use std::iter::Zip;
use std::mem;
Expand Down Expand Up @@ -1427,6 +1428,20 @@ pub struct PropertyValueSet {
}

impl PropertyValueSet {
/// Returns a HashMap mapping property names to info
pub fn as_hashmap(
&self,
device: &impl Device,
) -> Result<HashMap<String, property::Info>, SystemError> {
let mut map = HashMap::new();
for id in self.prop_ids.iter() {
let info = device.get_property(*id)?;
let name = info.name().to_str().unwrap().to_owned();
map.insert(name, info);
}
Ok(map)
}

/// Returns a pair representing a set of [`property::Handle`] and their raw values
pub fn as_props_and_values(&self) -> (&[property::Handle], &[property::RawValue]) {
(&self.prop_ids, &self.prop_vals)
Expand Down

0 comments on commit 61a7415

Please sign in to comment.