1 //! # Safe `libgbm` bindings for [rust](https://www.rust-lang.org)
2 //!
3 //! The Generic Buffer Manager
4 //!
5 //! This module provides an abstraction that the caller can use to request a
6 //! buffer from the underlying memory management system for the platform.
7 //!
8 //! This allows the creation of portable code whilst still allowing access to
9 //! the underlying memory manager.
10 //!
11 //! This library is best used in combination with [`drm-rs`](https://github.com/Smithay/drm-rs),
12 //! provided through the `drm-support` feature.
13 //!
14 //! ## Example
15 //!
16 //! ```rust,no_run
17 //! # extern crate drm;
18 //! # extern crate gbm;
19 //! # use drm::control::connector::Info as ConnectorInfo;
20 //! # use drm::control::Mode;
21 //! use drm::control::{self, crtc, framebuffer};
22 //! use gbm::{BufferObjectFlags, Device, Format};
23 //!
24 //! # use std::fs::{File, OpenOptions};
25 //! # use std::os::unix::io::{AsFd, BorrowedFd};
26 //! #
27 //! # use drm::control::Device as ControlDevice;
28 //! # use drm::Device as BasicDevice;
29 //! # struct Card(File);
30 //! #
31 //! # impl AsFd for Card {
32 //! #     fn as_fd(&self) -> BorrowedFd {
33 //! #         self.0.as_fd()
34 //! #     }
35 //! # }
36 //! #
37 //! # impl BasicDevice for Card {}
38 //! # impl ControlDevice for Card {}
39 //! #
40 //! # fn init_drm_device() -> Card {
41 //! #     let mut options = OpenOptions::new();
42 //! #     options.read(true);
43 //! #     options.write(true);
44 //! #     let file = options.open("/dev/dri/card0").unwrap();
45 //! #     Card(file)
46 //! # }
47 //! # fn main() {
48 //! // ... init your drm device ...
49 //! let drm = init_drm_device();
50 //!
51 //! // init a GBM device
52 //! let gbm = Device::new(drm).unwrap();
53 //!
54 //! // create a 4x4 buffer
55 //! let mut bo = gbm
56 //!     .create_buffer_object::<()>(
57 //!         1280,
58 //!         720,
59 //!         Format::Argb8888,
60 //!         BufferObjectFlags::SCANOUT | BufferObjectFlags::WRITE,
61 //!     )
62 //!     .unwrap();
63 //! // write something to it (usually use import or egl rendering instead)
64 //! let buffer = {
65 //!     let mut buffer = Vec::new();
66 //!     for i in 0..1280 {
67 //!         for _ in 0..720 {
68 //!             buffer.push(if i % 2 == 0 { 0 } else { 255 });
69 //!         }
70 //!     }
71 //!     buffer
72 //! };
73 //! bo.write(&buffer).unwrap();
74 //!
75 //! // create a framebuffer from our buffer
76 //! let fb = gbm.add_framebuffer(&bo, 32, 32).unwrap();
77 //!
78 //! # let res_handles = gbm.resource_handles().unwrap();
79 //! # let con = *res_handles.connectors().iter().next().unwrap();
80 //! # let crtc_handle = *res_handles.crtcs().iter().next().unwrap();
81 //! # let connector_info: ConnectorInfo = gbm.get_connector(con, false).unwrap();
82 //! # let mode: Mode = connector_info.modes()[0];
83 //! #
84 //! // display it (and get a crtc, mode and connector before)
85 //! gbm.set_crtc(crtc_handle, Some(fb), (0, 0), &[con], Some(mode))
86 //!     .unwrap();
87 //! # }
88 //! ```
89 #![warn(missing_debug_implementations)]
90 #![deny(missing_docs)]
91 
92 extern crate gbm_sys as ffi;
93 extern crate libc;
94 
95 #[cfg(feature = "import-wayland")]
96 extern crate wayland_server;
97 
98 #[cfg(feature = "drm-support")]
99 extern crate drm;
100 
101 extern crate drm_fourcc;
102 
103 #[macro_use]
104 extern crate bitflags;
105 
106 mod buffer_object;
107 mod device;
108 mod surface;
109 
110 pub use self::buffer_object::*;
111 pub use self::device::*;
112 pub use self::surface::*;
113 pub use drm_fourcc::{DrmFourcc as Format, DrmModifier as Modifier};
114 
115 use std::fmt;
116 use std::sync::{Arc, Weak};
117 
118 /// Trait for types that allow to obtain the underlying raw libinput pointer.
119 pub trait AsRaw<T> {
120     /// Receive a raw pointer representing this type.
as_raw(&self) -> *const T121     fn as_raw(&self) -> *const T;
122 
123     #[doc(hidden)]
as_raw_mut(&self) -> *mut T124     fn as_raw_mut(&self) -> *mut T {
125         self.as_raw() as *mut _
126     }
127 }
128 
129 struct PtrDrop<T>(*mut T, Option<Box<dyn FnOnce(*mut T) + Send + 'static>>);
130 
131 impl<T> Drop for PtrDrop<T> {
drop(&mut self)132     fn drop(&mut self) {
133         (self.1.take().unwrap())(self.0);
134     }
135 }
136 
137 #[derive(Clone)]
138 pub(crate) struct Ptr<T>(Arc<PtrDrop<T>>);
139 // SAFETY: The types used with Ptr in this crate are all Send (namely gbm_device, gbm_surface and gbm_bo).
140 // The type is private and can thus not be used unsoundly by other crates.
141 unsafe impl<T> Send for Ptr<T> {}
142 
143 impl<T> Ptr<T> {
new<F: FnOnce(*mut T) + Send + 'static>(ptr: *mut T, destructor: F) -> Ptr<T>144     fn new<F: FnOnce(*mut T) + Send + 'static>(ptr: *mut T, destructor: F) -> Ptr<T> {
145         Ptr(Arc::new(PtrDrop(ptr, Some(Box::new(destructor)))))
146     }
147 
downgrade(&self) -> WeakPtr<T>148     fn downgrade(&self) -> WeakPtr<T> {
149         WeakPtr(Arc::downgrade(&self.0))
150     }
151 }
152 
153 impl<T> std::ops::Deref for Ptr<T> {
154     type Target = *mut T;
155 
deref(&self) -> &Self::Target156     fn deref(&self) -> &Self::Target {
157         &(self.0).0
158     }
159 }
160 
161 impl<T> fmt::Pointer for Ptr<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error>162     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
163         fmt::Pointer::fmt(&self.0 .0, f)
164     }
165 }
166 
167 #[derive(Clone)]
168 pub(crate) struct WeakPtr<T>(Weak<PtrDrop<T>>);
169 
170 impl<T> WeakPtr<T> {
upgrade(&self) -> Option<Ptr<T>>171     fn upgrade(&self) -> Option<Ptr<T>> {
172         self.0.upgrade().map(Ptr)
173     }
174 }
175 
176 impl<T> fmt::Pointer for WeakPtr<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error>177     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
178         match self.upgrade() {
179             Some(x) => fmt::Pointer::fmt(&x, f),
180             None => fmt::Pointer::fmt(&std::ptr::null::<T>(), f),
181         }
182     }
183 }
184 
185 unsafe impl<T> Send for WeakPtr<T> where Ptr<T>: Send {}
186 
187 #[cfg(test)]
188 mod test {
189     use std::os::unix::io::OwnedFd;
190 
is_send<T: Send>()191     fn is_send<T: Send>() {}
192 
193     #[test]
device_is_send()194     fn device_is_send() {
195         is_send::<super::Device<std::fs::File>>();
196         is_send::<super::Device<OwnedFd>>();
197     }
198 
199     #[test]
surface_is_send()200     fn surface_is_send() {
201         is_send::<super::Surface<std::fs::File>>();
202         is_send::<super::Surface<OwnedFd>>();
203     }
204 
205     #[test]
unmapped_bo_is_send()206     fn unmapped_bo_is_send() {
207         is_send::<super::BufferObject<()>>();
208     }
209 }
210