summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..7d0c8cf
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,209 @@
+//! # Safe `libgbm` bindings for [rust](https://www.rust-lang.org)
+//!
+//! The Generic Buffer Manager
+//!
+//! This module provides an abstraction that the caller can use to request a
+//! buffer from the underlying memory management system for the platform.
+//!
+//! This allows the creation of portable code whilst still allowing access to
+//! the underlying memory manager.
+//!
+//! This library is best used in combination with [`drm-rs`](https://github.com/Smithay/drm-rs),
+//! provided through the `drm-support` feature.
+//!
+//! ## Example
+//!
+//! ```rust,no_run
+//! # extern crate drm;
+//! # extern crate gbm;
+//! # use drm::control::connector::Info as ConnectorInfo;
+//! # use drm::control::Mode;
+//! use drm::control::{self, crtc, framebuffer};
+//! use gbm::{BufferObjectFlags, Device, Format};
+//!
+//! # use std::fs::{File, OpenOptions};
+//! # use std::os::unix::io::{AsFd, BorrowedFd};
+//! #
+//! # use drm::control::Device as ControlDevice;
+//! # use drm::Device as BasicDevice;
+//! # struct Card(File);
+//! #
+//! # impl AsFd for Card {
+//! # fn as_fd(&self) -> BorrowedFd {
+//! # self.0.as_fd()
+//! # }
+//! # }
+//! #
+//! # impl BasicDevice for Card {}
+//! # impl ControlDevice for Card {}
+//! #
+//! # fn init_drm_device() -> Card {
+//! # let mut options = OpenOptions::new();
+//! # options.read(true);
+//! # options.write(true);
+//! # let file = options.open("/dev/dri/card0").unwrap();
+//! # Card(file)
+//! # }
+//! # fn main() {
+//! // ... init your drm device ...
+//! let drm = init_drm_device();
+//!
+//! // init a GBM device
+//! let gbm = Device::new(drm).unwrap();
+//!
+//! // create a 4x4 buffer
+//! let mut bo = gbm
+//! .create_buffer_object::<()>(
+//! 1280,
+//! 720,
+//! Format::Argb8888,
+//! BufferObjectFlags::SCANOUT | BufferObjectFlags::WRITE,
+//! )
+//! .unwrap();
+//! // write something to it (usually use import or egl rendering instead)
+//! let buffer = {
+//! let mut buffer = Vec::new();
+//! for i in 0..1280 {
+//! for _ in 0..720 {
+//! buffer.push(if i % 2 == 0 { 0 } else { 255 });
+//! }
+//! }
+//! buffer
+//! };
+//! bo.write(&buffer).unwrap();
+//!
+//! // create a framebuffer from our buffer
+//! let fb = gbm.add_framebuffer(&bo, 32, 32).unwrap();
+//!
+//! # let res_handles = gbm.resource_handles().unwrap();
+//! # let con = *res_handles.connectors().iter().next().unwrap();
+//! # let crtc_handle = *res_handles.crtcs().iter().next().unwrap();
+//! # let connector_info: ConnectorInfo = gbm.get_connector(con, false).unwrap();
+//! # let mode: Mode = connector_info.modes()[0];
+//! #
+//! // display it (and get a crtc, mode and connector before)
+//! gbm.set_crtc(crtc_handle, Some(fb), (0, 0), &[con], Some(mode))
+//! .unwrap();
+//! # }
+//! ```
+#![warn(missing_debug_implementations)]
+#![deny(missing_docs)]
+
+extern crate gbm_sys as ffi;
+extern crate libc;
+
+#[cfg(feature = "import-wayland")]
+extern crate wayland_server;
+
+#[cfg(feature = "drm-support")]
+extern crate drm;
+
+extern crate drm_fourcc;
+
+#[macro_use]
+extern crate bitflags;
+
+mod buffer_object;
+mod device;
+mod surface;
+
+pub use self::buffer_object::*;
+pub use self::device::*;
+pub use self::surface::*;
+pub use drm_fourcc::{DrmFourcc as Format, DrmModifier as Modifier};
+
+use std::fmt;
+use std::sync::{Arc, Weak};
+
+/// Trait for types that allow to obtain the underlying raw libinput pointer.
+pub trait AsRaw<T> {
+ /// Receive a raw pointer representing this type.
+ fn as_raw(&self) -> *const T;
+
+ #[doc(hidden)]
+ fn as_raw_mut(&self) -> *mut T {
+ self.as_raw() as *mut _
+ }
+}
+
+struct PtrDrop<T>(*mut T, Option<Box<dyn FnOnce(*mut T) + Send + 'static>>);
+
+impl<T> Drop for PtrDrop<T> {
+ fn drop(&mut self) {
+ (self.1.take().unwrap())(self.0);
+ }
+}
+
+#[derive(Clone)]
+pub(crate) struct Ptr<T>(Arc<PtrDrop<T>>);
+// SAFETY: The types used with Ptr in this crate are all Send (namely gbm_device, gbm_surface and gbm_bo).
+// The type is private and can thus not be used unsoundly by other crates.
+unsafe impl<T> Send for Ptr<T> {}
+
+impl<T> Ptr<T> {
+ fn new<F: FnOnce(*mut T) + Send + 'static>(ptr: *mut T, destructor: F) -> Ptr<T> {
+ Ptr(Arc::new(PtrDrop(ptr, Some(Box::new(destructor)))))
+ }
+
+ fn downgrade(&self) -> WeakPtr<T> {
+ WeakPtr(Arc::downgrade(&self.0))
+ }
+}
+
+impl<T> std::ops::Deref for Ptr<T> {
+ type Target = *mut T;
+
+ fn deref(&self) -> &Self::Target {
+ &(self.0).0
+ }
+}
+
+impl<T> fmt::Pointer for Ptr<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
+ fmt::Pointer::fmt(&self.0 .0, f)
+ }
+}
+
+#[derive(Clone)]
+pub(crate) struct WeakPtr<T>(Weak<PtrDrop<T>>);
+
+impl<T> WeakPtr<T> {
+ fn upgrade(&self) -> Option<Ptr<T>> {
+ self.0.upgrade().map(Ptr)
+ }
+}
+
+impl<T> fmt::Pointer for WeakPtr<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
+ match self.upgrade() {
+ Some(x) => fmt::Pointer::fmt(&x, f),
+ None => fmt::Pointer::fmt(&std::ptr::null::<T>(), f),
+ }
+ }
+}
+
+unsafe impl<T> Send for WeakPtr<T> where Ptr<T>: Send {}
+
+#[cfg(test)]
+mod test {
+ use std::os::unix::io::OwnedFd;
+
+ fn is_send<T: Send>() {}
+
+ #[test]
+ fn device_is_send() {
+ is_send::<super::Device<std::fs::File>>();
+ is_send::<super::Device<OwnedFd>>();
+ }
+
+ #[test]
+ fn surface_is_send() {
+ is_send::<super::Surface<std::fs::File>>();
+ is_send::<super::Surface<OwnedFd>>();
+ }
+
+ #[test]
+ fn unmapped_bo_is_send() {
+ is_send::<super::BufferObject<()>>();
+ }
+}