1 //! Helpers for atomic modesetting.
2 
3 use crate::control;
4 
5 /// Helper struct to construct atomic commit requests
6 #[derive(Debug, Clone, Default)]
7 pub struct AtomicModeReq {
8     pub(super) objects: Vec<control::RawResourceHandle>,
9     pub(super) count_props_per_object: Vec<u32>,
10     pub(super) props: Vec<control::property::Handle>,
11     pub(super) values: Vec<control::property::RawValue>,
12 }
13 
14 impl AtomicModeReq {
15     /// Create a new and empty atomic commit request
new() -> AtomicModeReq16     pub fn new() -> AtomicModeReq {
17         Self::default()
18     }
19 
20     /// Add a property and value pair for a given raw resource to the request
add_raw_property( &mut self, obj_id: control::RawResourceHandle, prop_id: control::property::Handle, value: control::property::RawValue, )21     pub fn add_raw_property(
22         &mut self,
23         obj_id: control::RawResourceHandle,
24         prop_id: control::property::Handle,
25         value: control::property::RawValue,
26     ) {
27         // add object if missing (also to count_props_per_object)
28         let (idx, prop_count) = match self.objects.binary_search(&obj_id) {
29             Ok(idx) => (idx, self.count_props_per_object[idx]),
30             Err(new_idx) => {
31                 self.objects.insert(new_idx, obj_id);
32                 self.count_props_per_object.insert(new_idx, 0);
33                 (new_idx, 0)
34             }
35         };
36 
37         // get start of our objects props
38         let prop_slice_start = self.count_props_per_object.iter().take(idx).sum::<u32>() as usize;
39         // get end
40         let prop_slice_end = prop_slice_start + prop_count as usize;
41 
42         // search for existing prop entry
43         match self.props[prop_slice_start..prop_slice_end]
44             .binary_search_by_key(&Into::<u32>::into(prop_id), |x| (*x).into())
45         {
46             // prop exists, override
47             Ok(prop_idx) => {
48                 self.values[prop_slice_start + prop_idx] = value;
49             }
50             Err(prop_idx) => {
51                 // increase prop count
52                 self.count_props_per_object[idx] += 1;
53                 // insert prop, insert value
54                 self.props.insert(prop_slice_start + prop_idx, prop_id);
55                 self.values.insert(prop_slice_start + prop_idx, value);
56             }
57         }
58     }
59 
60     /// Add a property and value pair for a given handle to the request
add_property<H>( &mut self, handle: H, property: control::property::Handle, value: control::property::Value, ) where H: control::ResourceHandle,61     pub fn add_property<H>(
62         &mut self,
63         handle: H,
64         property: control::property::Handle,
65         value: control::property::Value,
66     ) where
67         H: control::ResourceHandle,
68     {
69         self.add_raw_property(handle.into(), property, value.into())
70     }
71 }
72