linux_drm/
modeset.rs

1use alloc::vec::Vec;
2use core::ops::{BitAnd, BitOr};
3
4mod atomic;
5mod buffer;
6mod props;
7
8pub use atomic::*;
9pub use buffer::*;
10pub use props::*;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[repr(transparent)]
14pub struct FramebufferId(pub u32);
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17#[repr(transparent)]
18pub struct CrtcId(pub u32);
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21#[repr(transparent)]
22pub struct ConnectorId(pub u32);
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25#[repr(transparent)]
26pub struct EncoderId(pub u32);
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29#[repr(transparent)]
30pub struct PlaneId(pub u32);
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33#[repr(transparent)]
34pub struct BufferObjectId(pub u32);
35
36#[derive(Debug, Clone, Copy)]
37#[non_exhaustive]
38pub enum ObjectId {
39    Crtc(CrtcId),
40    Connector(ConnectorId),
41    Encoder(EncoderId),
42    Mode(u32),
43    Property(PropertyId),
44    Framebuffer(FramebufferId),
45    Blob(BlobId),
46    Plane(PlaneId),
47}
48
49impl ObjectId {
50    pub fn as_raw_type_and_id(self) -> (u32, u32) {
51        use crate::ioctl;
52        match self {
53            ObjectId::Crtc(id) => (ioctl::DRM_MODE_OBJECT_CRTC, id.0),
54            ObjectId::Connector(id) => (ioctl::DRM_MODE_OBJECT_CONNECTOR, id.0),
55            ObjectId::Encoder(id) => (ioctl::DRM_MODE_OBJECT_ENCODER, id.0),
56            ObjectId::Mode(id) => (ioctl::DRM_MODE_OBJECT_MODE, id),
57            ObjectId::Property(id) => (ioctl::DRM_MODE_OBJECT_PROPERTY, id.0),
58            ObjectId::Framebuffer(id) => (ioctl::DRM_MODE_OBJECT_FB, id.0),
59            ObjectId::Blob(id) => (ioctl::DRM_MODE_OBJECT_BLOB, id.0),
60            ObjectId::Plane(id) => (ioctl::DRM_MODE_OBJECT_PLANE, id.0),
61        }
62    }
63}
64
65impl From<CrtcId> for ObjectId {
66    fn from(value: CrtcId) -> Self {
67        Self::Crtc(value)
68    }
69}
70
71impl From<ConnectorId> for ObjectId {
72    fn from(value: ConnectorId) -> Self {
73        Self::Connector(value)
74    }
75}
76
77impl From<EncoderId> for ObjectId {
78    fn from(value: EncoderId) -> Self {
79        Self::Encoder(value)
80    }
81}
82
83impl From<PropertyId> for ObjectId {
84    fn from(value: PropertyId) -> Self {
85        Self::Property(value)
86    }
87}
88
89impl From<FramebufferId> for ObjectId {
90    fn from(value: FramebufferId) -> Self {
91        Self::Framebuffer(value)
92    }
93}
94
95impl From<BlobId> for ObjectId {
96    fn from(value: BlobId) -> Self {
97        Self::Blob(value)
98    }
99}
100
101impl From<PlaneId> for ObjectId {
102    fn from(value: PlaneId) -> Self {
103        Self::Plane(value)
104    }
105}
106
107#[derive(Debug)]
108pub struct CardResources {
109    pub fb_ids: Vec<FramebufferId>,
110    pub crtc_ids: Vec<CrtcId>,
111    pub connector_ids: Vec<ConnectorId>,
112    pub encoder_ids: Vec<EncoderId>,
113    pub plane_ids: Vec<PlaneId>,
114    pub min_width: u32,
115    pub max_width: u32,
116    pub min_height: u32,
117    pub max_height: u32,
118}
119
120#[derive(Debug)]
121pub struct ConnectorState {
122    pub id: ConnectorId,
123    pub current_encoder_id: EncoderId,
124    pub connector_type: ConnectorType,
125    pub connector_type_id: u32,
126    pub connection_state: ConnectionState,
127    pub width_mm: u32,
128    pub height_mm: u32,
129    pub subpixel_type: SubpixelType,
130    pub modes: Vec<ModeInfo>,
131    pub props: Vec<ModeProp>,
132    pub available_encoder_ids: Vec<u32>,
133}
134
135impl ConnectorState {
136    pub fn preferred_mode(&self) -> Option<&ModeInfo> {
137        for mode in &self.modes {
138            if (mode.typ & crate::ioctl::DRM_MODE_TYPE_PREFERRED) != 0 {
139                return Some(mode);
140            }
141        }
142        None
143    }
144}
145
146#[derive(Debug, PartialEq, Eq, Copy, Clone)]
147#[repr(u32)]
148pub enum ConnectionState {
149    Connected = 1,
150    Disconnected = 2,
151    Unknown = 3,
152}
153
154impl From<u32> for ConnectionState {
155    fn from(value: u32) -> Self {
156        match value {
157            1 => Self::Connected,
158            2 => Self::Disconnected,
159            _ => Self::Unknown,
160        }
161    }
162}
163
164#[derive(Debug, PartialEq, Eq, Clone, Copy)]
165#[repr(u32)]
166pub enum ConnectorType {
167    Unknown = 0,
168    Vga = 1,
169    DviI = 2,
170    DviD = 3,
171    DviA = 4,
172    Composite = 5,
173    SVideo = 6,
174    Lvds = 7,
175    Component = 8,
176    NinePinDin = 9,
177    DisplayPort = 10,
178    HdmiA = 11,
179    HdmiB = 12,
180    Tv = 13,
181    Edp = 14,
182    Virtual = 15,
183    Dsi = 16,
184    Dpi = 17,
185    Writeback = 18,
186    Spi = 19,
187    Usb = 20,
188    Other = !0, // Not used by kernel, but used by us if kernel returns something we don't know
189}
190
191impl From<u32> for ConnectorType {
192    #[inline]
193    fn from(value: u32) -> Self {
194        if value < 21 {
195            // Safety: all values in this range are valid representations
196            // of this enum, as described above.
197            unsafe { core::mem::transmute(value) }
198        } else {
199            Self::Other
200        }
201    }
202}
203
204#[derive(Debug)]
205pub struct EncoderState {
206    pub encoder_id: EncoderId,
207    pub encoder_type: u32,
208    pub current_crtc_id: CrtcId,
209    pub possible_crtcs: u32,
210    pub possible_clones: u32,
211}
212
213#[derive(Debug)]
214pub struct CrtcState {
215    pub crtc_id: CrtcId,
216    pub fb_id: FramebufferId,
217    pub x: u32,
218    pub y: u32,
219    pub gamma_size: u32,
220    pub mode_valid: u32,
221    pub mode: ModeInfo,
222}
223
224impl From<crate::ioctl::DrmModeCrtc> for CrtcState {
225    fn from(value: crate::ioctl::DrmModeCrtc) -> Self {
226        Self {
227            crtc_id: CrtcId(value.crtc_id),
228            fb_id: FramebufferId(value.fb_id),
229            x: value.x,
230            y: value.y,
231            gamma_size: value.gamma_size,
232            mode_valid: value.mode_valid,
233            mode: value.mode.into(),
234        }
235    }
236}
237
238#[derive(Debug)]
239pub struct PlaneState {
240    pub id: PlaneId,
241    pub crtc_id: CrtcId,
242    pub fb_id: FramebufferId,
243    pub possible_crtcs: u32,
244    pub gamma_size: u32,
245}
246
247#[derive(Debug)]
248pub struct ModeInfo {
249    pub name: Vec<u8>,
250    pub clock: u32,
251    pub hdisplay: u16,
252    pub hsync_start: u16,
253    pub hsync_end: u16,
254    pub htotal: u16,
255    pub hskew: u16,
256    pub vdisplay: u16,
257    pub vsync_start: u16,
258    pub vsync_end: u16,
259    pub vtotal: u16,
260    pub vscan: u16,
261    pub vrefresh: u32,
262    pub flags: u32,
263    pub typ: u32,
264}
265
266impl From<crate::ioctl::DrmModeInfo> for ModeInfo {
267    fn from(value: crate::ioctl::DrmModeInfo) -> Self {
268        let name = value.name[..].split(|c| *c == 0).next().unwrap();
269        let name: &[u8] = unsafe { core::mem::transmute(name) };
270        Self {
271            name: name.to_vec(),
272            clock: value.clock,
273            hdisplay: value.hdisplay,
274            hsync_start: value.hsync_start,
275            hsync_end: value.hsync_end,
276            htotal: value.htotal,
277            hskew: value.hskew,
278            vdisplay: value.vdisplay,
279            vsync_start: value.vsync_start,
280            vsync_end: value.vsync_end,
281            vtotal: value.vtotal,
282            vscan: value.vscan,
283            vrefresh: value.vrefresh,
284            flags: value.flags,
285            typ: value.typ,
286        }
287    }
288}
289
290impl From<&ModeInfo> for crate::ioctl::DrmModeInfo {
291    fn from(value: &ModeInfo) -> Self {
292        let mut name_raw = [0_8; 32];
293        let name_len = core::cmp::min(name_raw.len() - 1, value.name.len());
294        let name_raw_slice = &mut name_raw[0..name_len];
295        name_raw_slice
296            .copy_from_slice(unsafe { core::mem::transmute(&value.name.as_slice()[0..name_len]) });
297        Self {
298            clock: value.clock,
299            hdisplay: value.hdisplay,
300            hsync_start: value.hsync_start,
301            hsync_end: value.hsync_end,
302            htotal: value.htotal,
303            hskew: value.hskew,
304            vdisplay: value.vdisplay,
305            vsync_start: value.vsync_start,
306            vsync_end: value.vsync_end,
307            vtotal: value.vtotal,
308            vscan: value.vscan,
309            vrefresh: value.vrefresh,
310            flags: value.flags,
311            typ: value.typ,
312            name: name_raw,
313        }
314    }
315}
316
317#[derive(Debug)]
318#[repr(u32)]
319pub enum SubpixelType {
320    Unknown = 1,
321    HorizontalRgb = 2,
322    HorizontalBgr = 3,
323    VerticalRgb = 4,
324    VerticalBgr = 5,
325    None = 6,
326}
327
328impl From<u32> for SubpixelType {
329    fn from(value: u32) -> Self {
330        match value {
331            2 => Self::HorizontalRgb,
332            3 => Self::HorizontalBgr,
333            4 => Self::VerticalRgb,
334            5 => Self::VerticalBgr,
335            _ => Self::Unknown,
336        }
337    }
338}
339
340#[derive(Debug)]
341#[repr(transparent)]
342pub struct PageFlipFlags(u32);
343
344impl PageFlipFlags {
345    pub const NONE: Self = Self(0);
346    pub const EVENT: Self = Self(crate::ioctl::DRM_MODE_PAGE_FLIP_EVENT);
347    pub const ASYNC: Self = Self(crate::ioctl::DRM_MODE_PAGE_FLIP_ASYNC);
348}
349
350impl BitOr for PageFlipFlags {
351    type Output = Self;
352
353    #[inline(always)]
354    fn bitor(self, rhs: Self) -> Self::Output {
355        Self(self.0 | rhs.0)
356    }
357}
358
359impl BitAnd for PageFlipFlags {
360    type Output = Self;
361
362    #[inline(always)]
363    fn bitand(self, rhs: Self) -> Self::Output {
364        Self(self.0 | rhs.0)
365    }
366}
367
368impl From<PageFlipFlags> for u32 {
369    #[inline(always)]
370    fn from(value: PageFlipFlags) -> Self {
371        value.0
372    }
373}