linux_drm/modeset/
atomic.rs1use alloc::boxed::Box;
2use alloc::collections::BTreeMap;
3use alloc::vec::Vec;
4use core::iter;
5use core::ops::BitOr;
6
7use super::{IntoRawPropertyValue, ObjectId, PropertyId};
8
9#[derive(Debug)]
11pub struct AtomicRequest {
12 objs: BTreeMap<u32, AtomicRequestObj>,
13 total_props: u32,
14
15 drops: Vec<Box<dyn core::any::Any>>,
19}
20
21#[derive(Debug)]
22struct AtomicRequestObj {
23 prop_ids: Vec<u32>,
24 prop_values: Vec<u64>,
25}
26
27impl AtomicRequest {
28 pub fn new() -> Self {
29 Self {
30 objs: BTreeMap::new(),
31 total_props: 0,
32 drops: Vec::new(),
33 }
34 }
35
36 pub fn reset(&mut self) {
45 for (_, v) in self.objs.iter_mut() {
51 v.prop_ids.truncate(0);
52 v.prop_values.truncate(0);
53 }
54 self.total_props = 0;
55 self.drops.truncate(0);
56 }
57
58 pub fn set_property(
59 &mut self,
60 obj_id: impl Into<ObjectId>,
61 prop_id: PropertyId,
62 value: impl IntoRawPropertyValue,
63 ) {
64 fn set(req: &mut AtomicRequest, obj_id: ObjectId, prop_id: PropertyId, value: u64) {
65 let (_, obj_id) = obj_id.as_raw_type_and_id();
66 let obj = req.objs.entry(obj_id).or_insert_with(|| AtomicRequestObj {
67 prop_ids: Vec::new(),
68 prop_values: Vec::new(),
69 });
70
71 obj.prop_ids.reserve(1);
74 obj.prop_values.reserve(1);
75
76 obj.prop_ids.push(prop_id.0);
77 obj.prop_values.push(value);
78 req.total_props += 1; if req.objs.len() > (u32::MAX as usize) {
80 panic!("too many distinct objects in request");
81 }
82 }
83 let (raw_v, drop) = value.into_raw_property_value();
84 if let Some(drop) = drop {
85 self.drops.push(drop);
86 }
87 set(self, obj_id.into(), prop_id, raw_v);
88 }
89
90 pub(crate) fn for_ioctl_req(&self) -> AtomicRequestRawParts {
91 let obj_count = self.objs.len();
92 let mut obj_ids = Vec::<u32>::with_capacity(obj_count);
93 let mut obj_prop_counts = Vec::<u32>::with_capacity(obj_count);
94 let total_prop_count = self.total_props as usize;
95 let mut prop_ids = Vec::<u32>::with_capacity(total_prop_count);
96 let mut prop_values = Vec::<u64>::with_capacity(total_prop_count);
97
98 for (obj_id, obj) in self.objs.iter() {
99 obj_ids.push(*obj_id);
100 obj_prop_counts.push(obj.prop_ids.len() as u32);
101
102 for (prop_id, value) in iter::zip(
103 obj.prop_ids.iter().copied(),
104 obj.prop_values.iter().copied(),
105 ) {
106 prop_ids.push(prop_id);
107 prop_values.push(value);
108 }
109 }
110
111 AtomicRequestRawParts {
112 obj_ids,
113 obj_prop_counts,
114 prop_ids,
115 prop_values,
116 }
117 }
118}
119
120pub(crate) struct AtomicRequestRawParts {
121 pub(crate) obj_ids: Vec<u32>,
122 pub(crate) obj_prop_counts: Vec<u32>,
123 pub(crate) prop_ids: Vec<u32>,
124 pub(crate) prop_values: Vec<u64>,
125}
126
127pub struct AtomicCommitFlags(pub(crate) u32);
128
129impl AtomicCommitFlags {
130 pub const NONE: Self = Self(0);
131 pub const TEST_ONLY: Self = Self(crate::ioctl::DRM_MODE_ATOMIC_TEST_ONLY);
132 pub const NONBLOCK: Self = Self(crate::ioctl::DRM_MODE_ATOMIC_NONBLOCK);
133 pub const ALLOW_MODESET: Self = Self(crate::ioctl::DRM_MODE_ATOMIC_ALLOW_MODESET);
134 pub const PAGE_FLIP_EVENT: Self = Self(crate::ioctl::DRM_MODE_PAGE_FLIP_EVENT);
135 pub const ASYNC: Self = Self(crate::ioctl::DRM_MODE_PAGE_FLIP_ASYNC);
136}
137
138impl BitOr for AtomicCommitFlags {
139 type Output = Self;
140
141 fn bitor(self, rhs: Self) -> Self {
142 Self(self.0 | rhs.0)
143 }
144}