1 | //! Memory management and buffer functionality that the DRM subsystem exposes. |
2 | //! |
3 | //! # Summary |
4 | //! |
5 | //! The DRM subsystem exposes functionality for managing memory on modern GPU |
6 | //! devices using a system called the Graphics Execution Manager (GEM). This |
7 | //! system manages GPU buffers and exposes them to userspace using 32-bit |
8 | //! handles. These handles are automatically reference counted in the kernel. |
9 | //! |
10 | //! GEM provides a small API for sharing buffers between processes. However, it |
11 | //! does not provide any generic API for creating these. Instead, each driver |
12 | //! provides its own method of creating these buffers. The `libgbm` library |
13 | //! (part of the mesa project) provides a driver agnostic method of creating |
14 | //! these buffers. |
15 | //! |
16 | //! There are two methods of sharing a GEM handle between processes: |
17 | //! |
18 | //! 1. Using `Flink` to globally publish a handle using a 32-bit 'name'. This |
19 | //! requires either holding the DRM Master lock or having the process' |
20 | //! [`AuthToken`](struct@crate::AuthToken) authenticated. However, any process can |
21 | //! open these handles if they know (or even guess) the global name. |
22 | //! |
23 | //! 2. Converting the GEM handle into a PRIME file descriptor, and passing it |
24 | //! like a regular one. This allows better control and security, and is the |
25 | //! recommended method of sharing buffers. |
26 | |
27 | use control; |
28 | pub use drm_fourcc::{DrmFourcc, DrmModifier, DrmVendor, UnrecognizedFourcc, UnrecognizedVendor}; |
29 | |
30 | /// A handle to a GEM buffer |
31 | /// |
32 | /// # Notes |
33 | /// |
34 | /// There are no guarantees that this handle is valid. It is up to the user |
35 | /// to make sure this handle does not outlive the underlying buffer, and to |
36 | /// prevent buffers from leaking by properly closing them after they are done. |
37 | #[repr (transparent)] |
38 | #[derive (Copy, Clone, Hash, PartialEq, Eq)] |
39 | pub struct Handle(control::RawResourceHandle); |
40 | |
41 | // Safety: Handle is repr(transparent) over NonZeroU32 |
42 | unsafe impl bytemuck::ZeroableInOption for Handle {} |
43 | unsafe impl bytemuck::PodInOption for Handle {} |
44 | |
45 | impl From<Handle> for control::RawResourceHandle { |
46 | fn from(handle: Handle) -> Self { |
47 | handle.0 |
48 | } |
49 | } |
50 | |
51 | impl From<Handle> for u32 { |
52 | fn from(handle: Handle) -> Self { |
53 | handle.0.into() |
54 | } |
55 | } |
56 | |
57 | impl From<control::RawResourceHandle> for Handle { |
58 | fn from(handle: control::RawResourceHandle) -> Self { |
59 | Handle(handle) |
60 | } |
61 | } |
62 | |
63 | impl std::fmt::Debug for Handle { |
64 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
65 | f.debug_tuple(name:"buffer::Handle" ).field(&self.0).finish() |
66 | } |
67 | } |
68 | |
69 | /// The name of a GEM buffer. |
70 | /// |
71 | /// # Notes |
72 | /// |
73 | /// There are no guarantees that this name is valid. It is up to the user |
74 | /// to make sure this name does not outlive the underlying buffer, and to |
75 | /// prevent buffers from leaking by properly closing them after they are done. |
76 | #[repr (transparent)] |
77 | #[derive (Copy, Clone, Hash, PartialEq, Eq)] |
78 | pub struct Name(u32); |
79 | |
80 | impl From<Name> for u32 { |
81 | fn from(name: Name) -> u32 { |
82 | name.0 |
83 | } |
84 | } |
85 | |
86 | impl std::fmt::Debug for Name { |
87 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
88 | f.debug_tuple(name:"buffer::Name" ).field(&self.0).finish() |
89 | } |
90 | } |
91 | |
92 | /// Common functionality of all regular buffers. |
93 | pub trait Buffer { |
94 | /// The width and height of the buffer. |
95 | fn size(&self) -> (u32, u32); |
96 | /// The format of the buffer. |
97 | fn format(&self) -> DrmFourcc; |
98 | /// The pitch of the buffer. |
99 | fn pitch(&self) -> u32; |
100 | /// The handle to the buffer. |
101 | fn handle(&self) -> Handle; |
102 | } |
103 | |
104 | /// Planar buffers are buffers where each channel/plane is in its own buffer. |
105 | /// |
106 | /// Each plane has their own handle, pitch, and offsets. |
107 | pub trait PlanarBuffer { |
108 | /// The width and height of the buffer. |
109 | fn size(&self) -> (u32, u32); |
110 | /// The format of the buffer. |
111 | fn format(&self) -> DrmFourcc; |
112 | /// The pitches of the buffer. |
113 | fn pitches(&self) -> [u32; 4]; |
114 | /// The handles to the buffer. |
115 | fn handles(&self) -> [Option<Handle>; 4]; |
116 | /// The offsets of the buffer. |
117 | fn offsets(&self) -> [u32; 4]; |
118 | } |
119 | |