| 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 crate::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 modifier of the buffer. |
| 113 | fn modifier(&self) -> Option<DrmModifier>; |
| 114 | /// The pitches of the buffer. |
| 115 | fn pitches(&self) -> [u32; 4]; |
| 116 | /// The handles to the buffer. |
| 117 | fn handles(&self) -> [Option<Handle>; 4]; |
| 118 | /// The offsets of the buffer. |
| 119 | fn offsets(&self) -> [u32; 4]; |
| 120 | } |
| 121 | |