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, RawFd};
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
92extern crate gbm_sys as ffi;
93extern crate libc;
94
95#[cfg(feature = "import-wayland")]
96extern crate wayland_server;
97
98#[cfg(feature = "drm-support")]
99extern crate drm;
100
101extern crate drm_fourcc;
102
103#[macro_use]
104extern crate bitflags;
105
106mod buffer_object;
107mod device;
108mod surface;
109
110pub use self::buffer_object::*;
111pub use self::device::*;
112pub use self::surface::*;
113pub use drm_fourcc::{DrmFourcc as Format, DrmModifier as Modifier};
114
115use std::fmt;
116use std::sync::{Arc, Weak};
117
118/// Trait for types that allow to obtain the underlying raw libinput pointer.
119pub trait AsRaw<T> {
120 /// Receive a raw pointer representing this type.
121 fn as_raw(&self) -> *const T;
122
123 #[doc(hidden)]
124 fn as_raw_mut(&self) -> *mut T {
125 self.as_raw() as *mut _
126 }
127}
128
129struct PtrDrop<T>(*mut T, Option<Box<dyn FnOnce(*mut T) + Send + 'static>>);
130
131impl<T> Drop for PtrDrop<T> {
132 fn drop(&mut self) {
133 (self.1.take().unwrap())(self.0);
134 }
135}
136
137#[derive(Clone)]
138pub(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.
141unsafe impl<T> Send for Ptr<T> {}
142
143impl<T> Ptr<T> {
144 fn new<F: FnOnce(*mut T) + Send + 'static>(ptr: *mut T, destructor: F) -> Ptr<T> {
145 Ptr(Arc::new(data:PtrDrop(ptr, Some(Box::new(destructor)))))
146 }
147
148 fn downgrade(&self) -> WeakPtr<T> {
149 WeakPtr(Arc::downgrade(&self.0))
150 }
151}
152
153impl<T> std::ops::Deref for Ptr<T> {
154 type Target = *mut T;
155
156 fn deref(&self) -> &Self::Target {
157 &(self.0).0
158 }
159}
160
161impl<T> fmt::Pointer for Ptr<T> {
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)]
168pub(crate) struct WeakPtr<T>(Weak<PtrDrop<T>>);
169
170impl<T> WeakPtr<T> {
171 fn upgrade(&self) -> Option<Ptr<T>> {
172 self.0.upgrade().map(Ptr)
173 }
174}
175
176impl<T> fmt::Pointer for WeakPtr<T> {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
178 match self.upgrade() {
179 Some(x: Ptr) => fmt::Pointer::fmt(&x, f),
180 None => fmt::Pointer::fmt(&std::ptr::null::<T>(), f),
181 }
182 }
183}
184
185unsafe impl<T> Send for WeakPtr<T> where Ptr<T>: Send {}
186
187#[cfg(test)]
188mod test {
189 use std::os::unix::io::OwnedFd;
190
191 fn is_send<T: Send>() {}
192
193 #[test]
194 fn device_is_send() {
195 is_send::<super::Device<std::fs::File>>();
196 is_send::<super::Device<OwnedFd>>();
197 }
198
199 #[test]
200 fn surface_is_send() {
201 is_send::<super::Surface<std::fs::File>>();
202 is_send::<super::Surface<OwnedFd>>();
203 }
204
205 #[test]
206 fn unmapped_bo_is_send() {
207 is_send::<super::BufferObject<()>>();
208 }
209}
210