1//!
2//! Bindings to the DRM's modesetting capabilities.
3//!
4
5#![allow(clippy::too_many_arguments)]
6
7use crate::ioctl;
8use drm_sys::*;
9
10use std::{io, os::unix::io::BorrowedFd};
11
12/// Enumerate most card resources.
13pub fn get_resources(
14 fd: BorrowedFd<'_>,
15 mut fbs: Option<&mut Vec<u32>>,
16 mut crtcs: Option<&mut Vec<u32>>,
17 mut connectors: Option<&mut Vec<u32>>,
18 mut encoders: Option<&mut Vec<u32>>,
19) -> io::Result<drm_mode_card_res> {
20 let mut sizes = drm_mode_card_res::default();
21 unsafe {
22 ioctl::mode::get_resources(fd, &mut sizes)?;
23 }
24
25 map_reserve!(fbs, sizes.count_fbs as usize);
26 map_reserve!(crtcs, sizes.count_crtcs as usize);
27 map_reserve!(connectors, sizes.count_connectors as usize);
28 map_reserve!(encoders, sizes.count_encoders as usize);
29
30 let mut res = drm_mode_card_res {
31 fb_id_ptr: map_ptr!(&fbs),
32 crtc_id_ptr: map_ptr!(&crtcs),
33 connector_id_ptr: map_ptr!(&connectors),
34 encoder_id_ptr: map_ptr!(&encoders),
35 count_fbs: map_len!(&fbs),
36 count_crtcs: map_len!(&crtcs),
37 count_connectors: map_len!(&connectors),
38 count_encoders: map_len!(&encoders),
39 ..Default::default()
40 };
41
42 unsafe {
43 ioctl::mode::get_resources(fd, &mut res)?;
44 }
45
46 map_set!(fbs, res.count_fbs as usize);
47 map_set!(crtcs, res.count_crtcs as usize);
48 map_set!(connectors, res.count_connectors as usize);
49 map_set!(encoders, res.count_encoders as usize);
50
51 Ok(res)
52}
53
54/// Enumerate plane resources.
55pub fn get_plane_resources(
56 fd: BorrowedFd<'_>,
57 mut planes: Option<&mut Vec<u32>>,
58) -> io::Result<drm_mode_get_plane_res> {
59 let mut sizes = drm_mode_get_plane_res::default();
60 unsafe {
61 ioctl::mode::get_plane_resources(fd, &mut sizes)?;
62 }
63
64 if planes.is_none() {
65 return Ok(sizes);
66 }
67
68 map_reserve!(planes, sizes.count_planes as usize);
69
70 let mut res = drm_mode_get_plane_res {
71 plane_id_ptr: map_ptr!(&planes),
72 count_planes: sizes.count_planes,
73 };
74
75 unsafe {
76 ioctl::mode::get_plane_resources(fd, &mut res)?;
77 }
78
79 map_set!(planes, res.count_planes as usize);
80
81 Ok(res)
82}
83
84/// Get info about a framebuffer.
85pub fn get_framebuffer(fd: BorrowedFd<'_>, fb_id: u32) -> io::Result<drm_mode_fb_cmd> {
86 let mut info: drm_mode_fb_cmd = drm_mode_fb_cmd {
87 fb_id,
88 ..Default::default()
89 };
90
91 unsafe {
92 ioctl::mode::get_fb(fd, &mut info)?;
93 }
94
95 Ok(info)
96}
97
98/// Add a new framebuffer.
99pub fn add_fb(
100 fd: BorrowedFd<'_>,
101 width: u32,
102 height: u32,
103 pitch: u32,
104 bpp: u32,
105 depth: u32,
106 handle: u32,
107) -> io::Result<drm_mode_fb_cmd> {
108 let mut fb: drm_mode_fb_cmd = drm_mode_fb_cmd {
109 width,
110 height,
111 pitch,
112 bpp,
113 depth,
114 handle,
115 ..Default::default()
116 };
117
118 unsafe {
119 ioctl::mode::add_fb(fd, &mut fb)?;
120 }
121
122 Ok(fb)
123}
124
125/// Get info about a framebuffer (with modifiers).
126pub fn get_framebuffer2(fd: BorrowedFd<'_>, fb_id: u32) -> io::Result<drm_mode_fb_cmd2> {
127 let mut info: drm_mode_fb_cmd2 = drm_mode_fb_cmd2 {
128 fb_id,
129 ..Default::default()
130 };
131
132 unsafe {
133 ioctl::mode::get_fb2(fd, &mut info)?;
134 }
135
136 Ok(info)
137}
138
139/// Add a new framebuffer (with modifiers)
140pub fn add_fb2(
141 fd: BorrowedFd<'_>,
142 width: u32,
143 height: u32,
144 fmt: u32,
145 handles: &[u32; 4],
146 pitches: &[u32; 4],
147 offsets: &[u32; 4],
148 modifier: &[u64; 4],
149 flags: u32,
150) -> io::Result<drm_mode_fb_cmd2> {
151 let mut fb: drm_mode_fb_cmd2 = drm_mode_fb_cmd2 {
152 width,
153 height,
154 pixel_format: fmt,
155 flags,
156 handles: *handles,
157 pitches: *pitches,
158 offsets: *offsets,
159 modifier: *modifier,
160 ..Default::default()
161 };
162
163 unsafe {
164 ioctl::mode::add_fb2(fd, &mut fb)?;
165 }
166
167 Ok(fb)
168}
169
170/// Remove a framebuffer.
171pub fn rm_fb(fd: BorrowedFd<'_>, mut id: u32) -> io::Result<()> {
172 unsafe {
173 ioctl::mode::rm_fb(fd, &mut id)?;
174 }
175
176 Ok(())
177}
178
179/// Mark a framebuffer as dirty.
180pub fn dirty_fb(
181 fd: BorrowedFd<'_>,
182 fb_id: u32,
183 clips: &[drm_clip_rect],
184) -> io::Result<drm_mode_fb_dirty_cmd> {
185 let mut dirty: drm_mode_fb_dirty_cmd = drm_mode_fb_dirty_cmd {
186 fb_id,
187 num_clips: clips.len() as _,
188 clips_ptr: clips.as_ptr() as _,
189 ..Default::default()
190 };
191
192 unsafe {
193 ioctl::mode::dirty_fb(fd, &mut dirty)?;
194 }
195
196 Ok(dirty)
197}
198
199/// Get info about a CRTC
200pub fn get_crtc(fd: BorrowedFd<'_>, crtc_id: u32) -> io::Result<drm_mode_crtc> {
201 let mut info: drm_mode_crtc = drm_mode_crtc {
202 crtc_id,
203 ..Default::default()
204 };
205
206 unsafe {
207 ioctl::mode::get_crtc(fd, &mut info)?;
208 }
209
210 Ok(info)
211}
212
213/// Set CRTC state
214pub fn set_crtc(
215 fd: BorrowedFd<'_>,
216 crtc_id: u32,
217 fb_id: u32,
218 x: u32,
219 y: u32,
220 conns: &[u32],
221 mode: Option<drm_mode_modeinfo>,
222) -> io::Result<drm_mode_crtc> {
223 let mut crtc: drm_mode_crtc = drm_mode_crtc {
224 set_connectors_ptr: conns.as_ptr() as _,
225 count_connectors: conns.len() as _,
226 crtc_id,
227 fb_id,
228 x,
229 y,
230 mode_valid: match mode {
231 Some(_) => 1,
232 None => 0,
233 },
234 mode: mode.unwrap_or_default(),
235 ..Default::default()
236 };
237
238 unsafe {
239 ioctl::mode::set_crtc(fd, &mut crtc)?;
240 }
241
242 Ok(crtc)
243}
244
245/// Get CRTC gamma ramp
246pub fn get_gamma(
247 fd: BorrowedFd<'_>,
248 crtc_id: u32,
249 size: usize,
250 red: &mut [u16],
251 green: &mut [u16],
252 blue: &mut [u16],
253) -> io::Result<drm_mode_crtc_lut> {
254 let mut lut: drm_mode_crtc_lut = drm_mode_crtc_lut {
255 crtc_id,
256 gamma_size: size as _,
257 red: red.as_mut_ptr() as _,
258 green: green.as_mut_ptr() as _,
259 blue: blue.as_mut_ptr() as _,
260 };
261
262 unsafe {
263 ioctl::mode::get_gamma(fd, &mut lut)?;
264 }
265
266 Ok(lut)
267}
268
269/// Set CRTC gamma ramp
270pub fn set_gamma(
271 fd: BorrowedFd<'_>,
272 crtc_id: u32,
273 size: usize,
274 red: &[u16],
275 green: &[u16],
276 blue: &[u16],
277) -> io::Result<drm_mode_crtc_lut> {
278 let mut lut: drm_mode_crtc_lut = drm_mode_crtc_lut {
279 crtc_id,
280 gamma_size: size as _,
281 red: red.as_ptr() as _,
282 green: green.as_ptr() as _,
283 blue: blue.as_ptr() as _,
284 };
285
286 unsafe {
287 ioctl::mode::set_gamma(fd, &mut lut)?;
288 }
289
290 Ok(lut)
291}
292
293/// Set cursor state
294///
295/// The buffer must be allocated using the buffer manager of the driver (GEM or TTM). It is not
296/// allowed to be a dumb buffer.
297#[deprecated = "use a cursor plane instead"]
298pub fn set_cursor(
299 fd: BorrowedFd<'_>,
300 crtc_id: u32,
301 buf_id: u32,
302 width: u32,
303 height: u32,
304) -> io::Result<drm_mode_cursor> {
305 let mut cursor: drm_mode_cursor = drm_mode_cursor {
306 flags: DRM_MODE_CURSOR_BO,
307 crtc_id,
308 width,
309 height,
310 handle: buf_id,
311 ..Default::default()
312 };
313
314 unsafe {
315 ioctl::mode::cursor(fd, &mut cursor)?;
316 }
317
318 Ok(cursor)
319}
320
321/// Set cursor state (with hotspot position)
322///
323/// The buffer must be allocated using the buffer manager of the driver (GEM or TTM). It is not
324/// allowed to be a dumb buffer.
325///
326/// The hotspot position is used to coordinate the guest and host cursor location in case of
327/// virtualization.
328#[deprecated = "use a cursor plane instead"]
329pub fn set_cursor2(
330 fd: BorrowedFd<'_>,
331 crtc_id: u32,
332 buf_id: u32,
333 width: u32,
334 height: u32,
335 hot_x: i32,
336 hot_y: i32,
337) -> io::Result<drm_mode_cursor2> {
338 let mut cursor: drm_mode_cursor2 = drm_mode_cursor2 {
339 flags: DRM_MODE_CURSOR_BO,
340 crtc_id,
341 width,
342 height,
343 handle: buf_id,
344 hot_x,
345 hot_y,
346 ..Default::default()
347 };
348
349 unsafe {
350 ioctl::mode::cursor2(fd, &mut cursor)?;
351 }
352
353 Ok(cursor)
354}
355
356/// Move cursor
357#[deprecated = "use a cursor plane instead"]
358pub fn move_cursor(
359 fd: BorrowedFd<'_>,
360 crtc_id: u32,
361 x: i32,
362 y: i32,
363) -> io::Result<drm_mode_cursor> {
364 let mut cursor: drm_mode_cursor = drm_mode_cursor {
365 flags: DRM_MODE_CURSOR_MOVE,
366 crtc_id,
367 x,
368 y,
369 ..Default::default()
370 };
371
372 unsafe {
373 ioctl::mode::cursor(fd, &mut cursor)?;
374 }
375
376 Ok(cursor)
377}
378
379/// Get info about a connector
380pub fn get_connector(
381 fd: BorrowedFd<'_>,
382 connector_id: u32,
383 mut props: Option<&mut Vec<u32>>,
384 mut prop_values: Option<&mut Vec<u64>>,
385 mut modes: Option<&mut Vec<drm_mode_modeinfo>>,
386 mut encoders: Option<&mut Vec<u32>>,
387 force_probe: bool,
388) -> io::Result<drm_mode_get_connector> {
389 assert_eq!(props.is_some(), prop_values.is_some());
390
391 let tmp_mode = drm_mode_modeinfo::default();
392 let mut sizes = drm_mode_get_connector {
393 connector_id,
394 modes_ptr: if force_probe {
395 0
396 } else {
397 &tmp_mode as *const _ as _
398 },
399 count_modes: u32::from(!force_probe),
400 ..Default::default()
401 };
402
403 unsafe {
404 ioctl::mode::get_connector(fd, &mut sizes)?;
405 }
406
407 let info = loop {
408 map_reserve!(props, sizes.count_props as usize);
409 map_reserve!(prop_values, sizes.count_props as usize);
410 map_reserve!(modes, sizes.count_modes as usize);
411 map_reserve!(encoders, sizes.count_encoders as usize);
412
413 let mut info = drm_mode_get_connector {
414 connector_id,
415 encoders_ptr: map_ptr!(&encoders),
416 modes_ptr: match &mut modes {
417 Some(b) => b.as_mut_ptr() as _,
418 None => {
419 if force_probe {
420 0 as _
421 } else {
422 &tmp_mode as *const _ as _
423 }
424 }
425 },
426 props_ptr: map_ptr!(&props),
427 prop_values_ptr: map_ptr!(&prop_values),
428 count_modes: match &modes {
429 Some(b) => b.capacity() as _,
430 None => u32::from(!force_probe),
431 },
432 count_props: map_len!(&props),
433 count_encoders: map_len!(&encoders),
434 ..Default::default()
435 };
436
437 unsafe {
438 ioctl::mode::get_connector(fd, &mut info)?;
439 }
440
441 if info.count_modes == sizes.count_modes
442 && info.count_encoders == sizes.count_encoders
443 && info.count_props == sizes.count_props
444 {
445 break info;
446 } else {
447 sizes = info;
448 }
449 };
450
451 map_set!(modes, info.count_modes as usize);
452 map_set!(props, info.count_props as usize);
453 map_set!(prop_values, info.count_props as usize);
454 map_set!(encoders, info.count_encoders as usize);
455
456 Ok(info)
457}
458
459/// Get info about an encoder
460pub fn get_encoder(fd: BorrowedFd<'_>, encoder_id: u32) -> io::Result<drm_mode_get_encoder> {
461 let mut info: drm_mode_get_encoder = drm_mode_get_encoder {
462 encoder_id,
463 ..Default::default()
464 };
465
466 unsafe {
467 ioctl::mode::get_encoder(fd, &mut info)?;
468 }
469
470 Ok(info)
471}
472
473/// Get info about a plane.
474pub fn get_plane(
475 fd: BorrowedFd<'_>,
476 plane_id: u32,
477 mut formats: Option<&mut Vec<u32>>,
478) -> io::Result<drm_mode_get_plane> {
479 let mut sizes = drm_mode_get_plane {
480 plane_id,
481 ..Default::default()
482 };
483
484 unsafe {
485 ioctl::mode::get_plane(fd, &mut sizes)?;
486 }
487
488 if formats.is_none() {
489 return Ok(sizes);
490 }
491
492 map_reserve!(formats, sizes.count_format_types as usize);
493
494 let mut info = drm_mode_get_plane {
495 plane_id,
496 count_format_types: sizes.count_format_types,
497 format_type_ptr: map_ptr!(&formats),
498 ..Default::default()
499 };
500
501 unsafe {
502 ioctl::mode::get_plane(fd, &mut info)?;
503 }
504
505 map_set!(formats, info.count_format_types as usize);
506
507 Ok(info)
508}
509
510/// Set plane state.
511pub fn set_plane(
512 fd: BorrowedFd<'_>,
513 plane_id: u32,
514 crtc_id: u32,
515 fb_id: u32,
516 flags: u32,
517 crtc_x: i32,
518 crtc_y: i32,
519 crtc_w: u32,
520 crtc_h: u32,
521 src_x: u32,
522 src_y: u32,
523 src_w: u32,
524 src_h: u32,
525) -> io::Result<drm_mode_set_plane> {
526 let mut plane: drm_mode_set_plane = drm_mode_set_plane {
527 plane_id,
528 crtc_id,
529 fb_id,
530 flags,
531 crtc_x,
532 crtc_y,
533 crtc_w,
534 crtc_h,
535 src_x,
536 src_y,
537 src_h,
538 src_w,
539 };
540
541 unsafe {
542 ioctl::mode::set_plane(fd, &mut plane)?;
543 }
544
545 Ok(plane)
546}
547
548/// Get property
549pub fn get_property(
550 fd: BorrowedFd<'_>,
551 prop_id: u32,
552 mut values: Option<&mut Vec<u64>>,
553 mut enums: Option<&mut Vec<drm_mode_property_enum>>,
554) -> io::Result<drm_mode_get_property> {
555 let mut prop = drm_mode_get_property {
556 prop_id,
557 ..Default::default()
558 };
559
560 unsafe {
561 ioctl::mode::get_property(fd, &mut prop)?;
562 }
563
564 // There is no need to call get_property() twice if there is nothing else to retrieve.
565 if prop.count_values == 0 && prop.count_enum_blobs == 0 {
566 return Ok(prop);
567 }
568
569 map_reserve!(values, prop.count_values as usize);
570 map_reserve!(enums, prop.count_enum_blobs as usize);
571
572 prop.values_ptr = map_ptr!(&values);
573 prop.enum_blob_ptr = map_ptr!(&enums);
574
575 unsafe {
576 ioctl::mode::get_property(fd, &mut prop)?;
577 }
578
579 map_set!(values, prop.count_values as usize);
580 map_set!(enums, prop.count_enum_blobs as usize);
581
582 Ok(prop)
583}
584
585/// Set property
586pub fn set_connector_property(
587 fd: BorrowedFd<'_>,
588 connector_id: u32,
589 prop_id: u32,
590 value: u64,
591) -> io::Result<drm_mode_connector_set_property> {
592 let mut prop: drm_mode_connector_set_property = drm_mode_connector_set_property {
593 value,
594 prop_id,
595 connector_id,
596 };
597
598 unsafe {
599 ioctl::mode::connector_set_property(fd, &mut prop)?;
600 }
601
602 Ok(prop)
603}
604
605/// Get the value of a property blob
606pub fn get_property_blob(
607 fd: BorrowedFd<'_>,
608 blob_id: u32,
609 mut data: Option<&mut Vec<u8>>,
610) -> io::Result<drm_mode_get_blob> {
611 let mut sizes = drm_mode_get_blob {
612 blob_id,
613 ..Default::default()
614 };
615
616 unsafe {
617 ioctl::mode::get_blob(fd, &mut sizes)?;
618 }
619
620 if data.is_none() {
621 return Ok(sizes);
622 }
623
624 map_reserve!(data, sizes.length as usize);
625
626 let mut blob = drm_mode_get_blob {
627 blob_id,
628 length: sizes.length,
629 data: map_ptr!(&data),
630 };
631
632 unsafe {
633 ioctl::mode::get_blob(fd, &mut blob)?;
634 }
635
636 map_set!(data, blob.length as usize);
637
638 Ok(blob)
639}
640
641/// Create a property blob
642pub fn create_property_blob(
643 fd: BorrowedFd<'_>,
644 data: &mut [u8],
645) -> io::Result<drm_mode_create_blob> {
646 let mut blob: drm_mode_create_blob = drm_mode_create_blob {
647 data: data.as_mut_ptr() as _,
648 length: data.len() as _,
649 ..Default::default()
650 };
651
652 unsafe {
653 ioctl::mode::create_blob(fd, &mut blob)?;
654 }
655
656 Ok(blob)
657}
658
659/// Destroy a property blob
660pub fn destroy_property_blob(fd: BorrowedFd<'_>, id: u32) -> io::Result<drm_mode_destroy_blob> {
661 let mut blob: drm_mode_destroy_blob = drm_mode_destroy_blob { blob_id: id };
662
663 unsafe {
664 ioctl::mode::destroy_blob(fd, &mut blob)?;
665 }
666
667 Ok(blob)
668}
669
670/// Get properties from an object
671pub fn get_properties(
672 fd: BorrowedFd<'_>,
673 obj_id: u32,
674 obj_type: u32,
675 mut props: Option<&mut Vec<u32>>,
676 mut values: Option<&mut Vec<u64>>,
677) -> io::Result<drm_mode_obj_get_properties> {
678 assert_eq!(props.is_some(), values.is_some());
679
680 let mut sizes = drm_mode_obj_get_properties {
681 obj_id,
682 obj_type,
683 ..Default::default()
684 };
685
686 unsafe {
687 ioctl::mode::obj_get_properties(fd, &mut sizes)?;
688 }
689
690 map_reserve!(props, sizes.count_props as usize);
691 map_reserve!(values, sizes.count_props as usize);
692
693 let mut info = drm_mode_obj_get_properties {
694 props_ptr: map_ptr!(&props),
695 prop_values_ptr: map_ptr!(&values),
696 count_props: map_len!(&props),
697 obj_id,
698 obj_type,
699 };
700
701 unsafe {
702 ioctl::mode::obj_get_properties(fd, &mut info)?;
703 }
704
705 map_set!(props, info.count_props as usize);
706 map_set!(values, info.count_props as usize);
707
708 Ok(info)
709}
710
711/// Set the properties of an object
712pub fn set_property(
713 fd: BorrowedFd<'_>,
714 prop_id: u32,
715 obj_id: u32,
716 obj_type: u32,
717 value: u64,
718) -> io::Result<()> {
719 let mut prop: drm_mode_obj_set_property = drm_mode_obj_set_property {
720 value,
721 prop_id,
722 obj_id,
723 obj_type,
724 };
725
726 unsafe {
727 ioctl::mode::obj_set_property(fd, &mut prop)?;
728 }
729
730 Ok(())
731}
732
733/// Schedule a page flip
734pub fn page_flip(
735 fd: BorrowedFd<'_>,
736 crtc_id: u32,
737 fb_id: u32,
738 flags: u32,
739 sequence: u32,
740) -> io::Result<()> {
741 let mut flip: drm_mode_crtc_page_flip = drm_mode_crtc_page_flip {
742 crtc_id,
743 fb_id,
744 flags,
745 // Same struct as drm_mode_crtc_page_flip_target
746 reserved: sequence,
747 user_data: crtc_id as _,
748 };
749
750 unsafe {
751 ioctl::mode::crtc_page_flip(fd, &mut flip)?;
752 }
753
754 Ok(())
755}
756
757/// Atomically set properties
758pub fn atomic_commit(
759 fd: BorrowedFd<'_>,
760 flags: u32,
761 objs: &mut [u32],
762 prop_counts: &mut [u32],
763 props: &mut [u32],
764 values: &mut [u64],
765) -> io::Result<()> {
766 let mut atomic: drm_mode_atomic = drm_mode_atomic {
767 flags,
768 count_objs: objs.len() as _,
769 objs_ptr: objs.as_mut_ptr() as _,
770 count_props_ptr: prop_counts.as_mut_ptr() as _,
771 props_ptr: props.as_mut_ptr() as _,
772 prop_values_ptr: values.as_mut_ptr() as _,
773 ..Default::default()
774 };
775
776 unsafe {
777 ioctl::mode::atomic(fd, &mut atomic)?;
778 }
779
780 Ok(())
781}
782
783/// Create a drm lease
784pub fn create_lease(
785 fd: BorrowedFd<'_>,
786 objects: &[u32],
787 flags: u32,
788) -> io::Result<drm_mode_create_lease> {
789 let mut data: drm_mode_create_lease = drm_mode_create_lease {
790 object_ids: objects.as_ptr() as _,
791 object_count: objects.len() as u32,
792 flags,
793 ..Default::default()
794 };
795
796 unsafe {
797 ioctl::mode::create_lease(fd, &mut data)?;
798 }
799
800 Ok(data)
801}
802
803/// List all active drm leases
804pub fn list_lessees(
805 fd: BorrowedFd<'_>,
806 mut lessees: Option<&mut Vec<u32>>,
807) -> io::Result<drm_mode_list_lessees> {
808 let mut sizes: drm_mode_list_lessees = drm_mode_list_lessees::default();
809
810 unsafe {
811 ioctl::mode::list_lessees(fd, &mut sizes)?;
812 };
813
814 map_reserve!(lessees, sizes.count_lessees as usize);
815
816 let mut data: drm_mode_list_lessees = drm_mode_list_lessees {
817 lessees_ptr: map_ptr!(&lessees),
818 count_lessees: map_len!(&lessees),
819 ..Default::default()
820 };
821
822 unsafe {
823 ioctl::mode::list_lessees(fd, &mut data)?;
824 };
825
826 map_set!(lessees, data.count_lessees as usize);
827
828 Ok(data)
829}
830
831/// Get leased objects for a lease file descriptor
832pub fn get_lease(
833 fd: BorrowedFd<'_>,
834 mut objects: Option<&mut Vec<u32>>,
835) -> io::Result<drm_mode_get_lease> {
836 let mut sizes: drm_mode_get_lease = drm_mode_get_lease::default();
837
838 unsafe {
839 ioctl::mode::get_lease(fd, &mut sizes)?;
840 }
841
842 map_reserve!(objects, sizes.count_objects as usize);
843
844 let mut data: drm_mode_get_lease = drm_mode_get_lease {
845 count_objects: map_len!(&objects),
846 objects_ptr: map_ptr!(&objects),
847 ..Default::default()
848 };
849
850 unsafe {
851 ioctl::mode::get_lease(fd, &mut data)?;
852 }
853
854 map_set!(objects, data.count_objects as usize);
855
856 Ok(data)
857}
858
859/// Revoke previously issued lease
860pub fn revoke_lease(fd: BorrowedFd<'_>, lessee_id: u32) -> io::Result<()> {
861 let mut data: drm_mode_revoke_lease = drm_mode_revoke_lease { lessee_id };
862
863 unsafe {
864 ioctl::mode::revoke_lease(fd, &mut data)?;
865 }
866
867 Ok(())
868}
869
870///
871/// Dumbbuffers are basic buffers that can be used for scanout.
872///
873pub mod dumbbuffer {
874 use crate::ioctl;
875 use drm_sys::*;
876
877 use std::{io, os::unix::io::BorrowedFd};
878
879 /// Create a dumb buffer
880 pub fn create(
881 fd: BorrowedFd<'_>,
882 width: u32,
883 height: u32,
884 bpp: u32,
885 flags: u32,
886 ) -> io::Result<drm_mode_create_dumb> {
887 let mut db = drm_mode_create_dumb {
888 height,
889 width,
890 bpp,
891 flags,
892 ..Default::default()
893 };
894
895 unsafe {
896 ioctl::mode::create_dumb(fd, &mut db)?;
897 }
898
899 Ok(db)
900 }
901
902 /// Destroy a dumb buffer
903 pub fn destroy(fd: BorrowedFd<'_>, handle: u32) -> io::Result<drm_mode_destroy_dumb> {
904 let mut db = drm_mode_destroy_dumb { handle };
905
906 unsafe {
907 ioctl::mode::destroy_dumb(fd, &mut db)?;
908 }
909
910 Ok(db)
911 }
912
913 /// Map a dump buffer and prep it for an mmap
914 pub fn map(
915 fd: BorrowedFd<'_>,
916 handle: u32,
917 pad: u32,
918 offset: u64,
919 ) -> io::Result<drm_mode_map_dumb> {
920 let mut map = drm_mode_map_dumb {
921 handle,
922 pad,
923 offset,
924 };
925
926 unsafe {
927 ioctl::mode::map_dumb(fd, &mut map)?;
928 }
929
930 Ok(map)
931 }
932}
933