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