| 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 |
| 16 | pub fn new() -> AtomicModeReq { |
| 17 | Self::default() |
| 18 | } |
| 19 | |
| 20 | /// Add a property and value pair for a given raw resource to the request |
| 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 |
| 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 | |