1 use crate::{AsRaw, Device, DeviceDestroyedError, Format, Modifier, Ptr, WeakPtr};
2 
3 #[cfg(feature = "drm-support")]
4 use drm::buffer::{Buffer as DrmBuffer, Handle, PlanarBuffer as DrmPlanarBuffer};
5 use std::os::unix::io::{AsFd, BorrowedFd, FromRawFd, OwnedFd};
6 
7 use std::error;
8 use std::fmt;
9 use std::io::{Error as IoError, Result as IoResult};
10 use std::marker::PhantomData;
11 use std::ops::{Deref, DerefMut};
12 use std::ptr;
13 use std::slice;
14 
15 /// A GBM buffer object
16 pub struct BufferObject<T: 'static> {
17     pub(crate) ffi: Ptr<ffi::gbm_bo>,
18     pub(crate) _device: WeakPtr<ffi::gbm_device>,
19     pub(crate) _userdata: PhantomData<T>,
20 }
21 
22 impl<T> fmt::Debug for BufferObject<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result23     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24         f.debug_struct("BufferObject")
25             .field("ptr", &format_args!("{:p}", self.ffi))
26             .field("device", &format_args!("{:p}", &self._device))
27             .field("width", &self.width().unwrap_or(0))
28             .field("height", &self.height().unwrap_or(0))
29             .field("offsets", &self.offsets())
30             .field("stride", &self.stride().unwrap_or(0))
31             .field("format", &self.format().ok())
32             .field("modifier", &self.modifier().ok())
33             .finish()
34     }
35 }
36 
37 bitflags! {
38     /// Flags to indicate the intended use for the buffer - these are passed into
39     /// [`Device::create_buffer_object()`].
40     ///
41     /// Use [`Device::is_format_supported()`] to check if the combination of format
42     /// and use flags are supported
43     #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent))]
44     #[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
45     pub struct BufferObjectFlags: u32 {
46         /// Buffer is going to be presented to the screen using an API such as KMS
47         const SCANOUT      = ffi::gbm_bo_flags::GBM_BO_USE_SCANOUT as u32;
48         /// Buffer is going to be used as cursor
49         const CURSOR       = ffi::gbm_bo_flags::GBM_BO_USE_CURSOR as u32;
50         /// Buffer is going to be used as cursor (deprecated)
51         #[deprecated = "Use CURSOR instead"]
52         const CURSOR_64X64 = ffi::gbm_bo_flags::GBM_BO_USE_CURSOR_64X64 as u32;
53         /// Buffer is to be used for rendering - for example it is going to be used
54         /// as the storage for a color buffer
55         const RENDERING    = ffi::gbm_bo_flags::GBM_BO_USE_RENDERING as u32;
56         /// Buffer can be used for [`BufferObject::write()`].  This is guaranteed to work
57         /// with [`Self::CURSOR`], but may not work for other combinations.
58         const WRITE        = ffi::gbm_bo_flags::GBM_BO_USE_WRITE as u32;
59         /// Buffer is linear, i.e. not tiled.
60         const LINEAR       = ffi::gbm_bo_flags::GBM_BO_USE_LINEAR as u32;
61         /// Buffer is protected
62         const PROTECTED    = ffi::gbm_bo_flags::GBM_BO_USE_PROTECTED as u32;
63     }
64 }
65 
66 /// Abstraction representing the handle to a buffer allocated by the manager
67 pub type BufferObjectHandle = ffi::gbm_bo_handle;
68 
69 enum BORef<'a, T: 'static> {
70     Ref(&'a BufferObject<T>),
71     Mut(&'a mut BufferObject<T>),
72 }
73 
74 /// A mapped buffer object
75 pub struct MappedBufferObject<'a, T: 'static> {
76     bo: BORef<'a, T>,
77     buffer: &'a mut [u8],
78     data: *mut ::libc::c_void,
79     stride: u32,
80     height: u32,
81     width: u32,
82     x: u32,
83     y: u32,
84 }
85 
86 impl<'a, T> fmt::Debug for MappedBufferObject<'a, T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result87     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88         f.debug_struct("MappedBufferObject")
89             .field(
90                 "mode",
91                 &match self.bo {
92                     BORef::Ref(_) => format_args!("read"),
93                     BORef::Mut(_) => format_args!("write"),
94                 },
95             )
96             .field(
97                 "buffer",
98                 match &self.bo {
99                     BORef::Ref(bo) => *bo,
100                     BORef::Mut(bo) => *bo,
101                 },
102             )
103             .finish()
104     }
105 }
106 
107 impl<'a, T: 'static> MappedBufferObject<'a, T> {
108     /// Get the stride of the buffer object
109     ///
110     /// This is calculated by the backend when it does the allocation of the buffer.
stride(&self) -> u32111     pub fn stride(&self) -> u32 {
112         self.stride
113     }
114 
115     /// The height of the mapped region for the buffer
height(&self) -> u32116     pub fn height(&self) -> u32 {
117         self.height
118     }
119 
120     /// The width of the mapped region for the buffer
width(&self) -> u32121     pub fn width(&self) -> u32 {
122         self.width
123     }
124 
125     /// The X (top left origin) starting position of the mapped region for the buffer
x(&self) -> u32126     pub fn x(&self) -> u32 {
127         self.x
128     }
129 
130     /// The Y (top left origin) starting position of the mapped region for the buffer
y(&self) -> u32131     pub fn y(&self) -> u32 {
132         self.y
133     }
134 
135     /// Access to the underlying image buffer
buffer(&self) -> &[u8]136     pub fn buffer(&self) -> &[u8] {
137         self.buffer
138     }
139 
140     /// Mutable access to the underlying image buffer
buffer_mut(&mut self) -> &mut [u8]141     pub fn buffer_mut(&mut self) -> &mut [u8] {
142         self.buffer
143     }
144 }
145 
146 impl<'a, T: 'static> Deref for MappedBufferObject<'a, T> {
147     type Target = BufferObject<T>;
deref(&self) -> &BufferObject<T>148     fn deref(&self) -> &BufferObject<T> {
149         match &self.bo {
150             BORef::Ref(bo) => bo,
151             BORef::Mut(bo) => bo,
152         }
153     }
154 }
155 
156 impl<'a, T: 'static> DerefMut for MappedBufferObject<'a, T> {
deref_mut(&mut self) -> &mut BufferObject<T>157     fn deref_mut(&mut self) -> &mut BufferObject<T> {
158         match &mut self.bo {
159             BORef::Ref(_) => unreachable!(),
160             BORef::Mut(bo) => bo,
161         }
162     }
163 }
164 
165 impl<'a, T: 'static> Drop for MappedBufferObject<'a, T> {
drop(&mut self)166     fn drop(&mut self) {
167         let ffi = match &self.bo {
168             BORef::Ref(bo) => &bo.ffi,
169             BORef::Mut(bo) => &bo.ffi,
170         };
171         unsafe { ffi::gbm_bo_unmap(**ffi, self.data) }
172     }
173 }
174 
destroy<T: 'static>(_: *mut ffi::gbm_bo, ptr: *mut ::libc::c_void)175 unsafe extern "C" fn destroy<T: 'static>(_: *mut ffi::gbm_bo, ptr: *mut ::libc::c_void) {
176     let ptr = ptr as *mut T;
177     if !ptr.is_null() {
178         let _ = Box::from_raw(ptr);
179     }
180 }
181 
182 impl<T: 'static> BufferObject<T> {
183     /// Get the width of the buffer object
width(&self) -> Result<u32, DeviceDestroyedError>184     pub fn width(&self) -> Result<u32, DeviceDestroyedError> {
185         self._device.upgrade().ok_or(DeviceDestroyedError)?;
186         Ok(unsafe { ffi::gbm_bo_get_width(*self.ffi) })
187     }
188 
189     /// Get the height of the buffer object
height(&self) -> Result<u32, DeviceDestroyedError>190     pub fn height(&self) -> Result<u32, DeviceDestroyedError> {
191         self._device.upgrade().ok_or(DeviceDestroyedError)?;
192         Ok(unsafe { ffi::gbm_bo_get_height(*self.ffi) })
193     }
194 
195     /// Get the stride of the buffer object
stride(&self) -> Result<u32, DeviceDestroyedError>196     pub fn stride(&self) -> Result<u32, DeviceDestroyedError> {
197         self._device.upgrade().ok_or(DeviceDestroyedError)?;
198         Ok(unsafe { ffi::gbm_bo_get_stride(*self.ffi) })
199     }
200 
201     /// Get the stride of the buffer object
stride_for_plane(&self, plane: i32) -> Result<u32, DeviceDestroyedError>202     pub fn stride_for_plane(&self, plane: i32) -> Result<u32, DeviceDestroyedError> {
203         self._device.upgrade().ok_or(DeviceDestroyedError)?;
204         Ok(unsafe { ffi::gbm_bo_get_stride_for_plane(*self.ffi, plane) })
205     }
206 
207     /// Get the format of the buffer object
format(&self) -> Result<Format, DeviceDestroyedError>208     pub fn format(&self) -> Result<Format, DeviceDestroyedError> {
209         self._device.upgrade().ok_or(DeviceDestroyedError)?;
210         Ok(
211             Format::try_from(unsafe { ffi::gbm_bo_get_format(*self.ffi) })
212                 .expect("libgbm returned invalid buffer format"),
213         )
214     }
215 
216     /// Get the bits per pixel of the buffer object
bpp(&self) -> Result<u32, DeviceDestroyedError>217     pub fn bpp(&self) -> Result<u32, DeviceDestroyedError> {
218         self._device.upgrade().ok_or(DeviceDestroyedError)?;
219         Ok(unsafe { ffi::gbm_bo_get_bpp(*self.ffi) })
220     }
221 
222     /// Get the offset for a plane of the buffer object
offset(&self, plane: i32) -> Result<u32, DeviceDestroyedError>223     pub fn offset(&self, plane: i32) -> Result<u32, DeviceDestroyedError> {
224         self._device.upgrade().ok_or(DeviceDestroyedError)?;
225         Ok(unsafe { ffi::gbm_bo_get_offset(*self.ffi, plane) })
226     }
227 
228     /// Get the plane count of the buffer object
plane_count(&self) -> Result<u32, DeviceDestroyedError>229     pub fn plane_count(&self) -> Result<u32, DeviceDestroyedError> {
230         self._device.upgrade().ok_or(DeviceDestroyedError)?;
231         Ok(unsafe { ffi::gbm_bo_get_plane_count(*self.ffi) as u32 })
232     }
233 
234     /// Get the modifier of the buffer object
modifier(&self) -> Result<Modifier, DeviceDestroyedError>235     pub fn modifier(&self) -> Result<Modifier, DeviceDestroyedError> {
236         self._device.upgrade().ok_or(DeviceDestroyedError)?;
237         Ok(Modifier::from(unsafe {
238             ffi::gbm_bo_get_modifier(*self.ffi)
239         }))
240     }
241 
242     /// Get a DMA-BUF file descriptor for the buffer object
243     ///
244     /// This function creates a DMA-BUF (also known as PRIME) file descriptor
245     /// handle for the buffer object.  Each call to [`Self::fd()`] returns a new
246     /// file descriptor and the caller is responsible for closing the file
247     /// descriptor.
fd(&self) -> Result<OwnedFd, FdError>248     pub fn fd(&self) -> Result<OwnedFd, FdError> {
249         self._device.upgrade().ok_or(DeviceDestroyedError)?;
250         unsafe {
251             let fd = ffi::gbm_bo_get_fd(*self.ffi);
252 
253             if fd == -1 {
254                 return Err(InvalidFdError.into());
255             }
256 
257             Ok(OwnedFd::from_raw_fd(fd))
258         }
259     }
260 
261     /// Get the file descriptor of the gbm device of this buffer object
device_fd(&self) -> Result<BorrowedFd, DeviceDestroyedError>262     pub fn device_fd(&self) -> Result<BorrowedFd, DeviceDestroyedError> {
263         let device_ptr = self._device.upgrade().ok_or(DeviceDestroyedError)?;
264         Ok(unsafe { BorrowedFd::borrow_raw(ffi::gbm_device_get_fd(*device_ptr)) })
265     }
266 
267     /// Get the handle of the buffer object
268     ///
269     /// This is stored in the platform generic union [`BufferObjectHandle`] type.  However
270     /// the format of this handle is platform specific.
handle(&self) -> Result<BufferObjectHandle, DeviceDestroyedError>271     pub fn handle(&self) -> Result<BufferObjectHandle, DeviceDestroyedError> {
272         self._device.upgrade().ok_or(DeviceDestroyedError)?;
273         Ok(unsafe { ffi::gbm_bo_get_handle(*self.ffi) })
274     }
275 
276     /// Get a DMA-BUF file descriptor for a plane of the buffer object
277     ///
278     /// This function creates a DMA-BUF (also known as PRIME) file descriptor
279     /// handle for a plane of the buffer object. Each call to [`Self::fd_for_plane()`]
280     /// returns a new file descriptor and the caller is responsible for closing
281     /// the file descriptor.
fd_for_plane(&self, plane: i32) -> Result<OwnedFd, FdError>282     pub fn fd_for_plane(&self, plane: i32) -> Result<OwnedFd, FdError> {
283         self._device.upgrade().ok_or(DeviceDestroyedError)?;
284         unsafe {
285             let fd = ffi::gbm_bo_get_fd_for_plane(*self.ffi, plane);
286 
287             if fd == -1 {
288                 return Err(InvalidFdError.into());
289             }
290 
291             Ok(OwnedFd::from_raw_fd(fd))
292         }
293     }
294 
295     /// Get the handle of a plane of the buffer object
296     ///
297     /// This is stored in the platform generic union [`BufferObjectHandle`] type.  However
298     /// the format of this handle is platform specific.
handle_for_plane(&self, plane: i32) -> Result<BufferObjectHandle, DeviceDestroyedError>299     pub fn handle_for_plane(&self, plane: i32) -> Result<BufferObjectHandle, DeviceDestroyedError> {
300         self._device.upgrade().ok_or(DeviceDestroyedError)?;
301         Ok(unsafe { ffi::gbm_bo_get_handle_for_plane(*self.ffi, plane) })
302     }
303 
304     /// Map a region of a GBM buffer object for cpu access
305     ///
306     /// This function maps a region of a GBM bo for cpu read access.
map<'a, D, F, S>( &'a self, device: &Device<D>, x: u32, y: u32, width: u32, height: u32, f: F, ) -> Result<IoResult<S>, WrongDeviceError> where D: AsFd + 'static, F: FnOnce(&MappedBufferObject<'a, T>) -> S,307     pub fn map<'a, D, F, S>(
308         &'a self,
309         device: &Device<D>,
310         x: u32,
311         y: u32,
312         width: u32,
313         height: u32,
314         f: F,
315     ) -> Result<IoResult<S>, WrongDeviceError>
316     where
317         D: AsFd + 'static,
318         F: FnOnce(&MappedBufferObject<'a, T>) -> S,
319     {
320         let device_ref = self._device.upgrade().ok_or(WrongDeviceError)?;
321         if *device_ref != device.as_raw_mut() {
322             // not matching
323             return Err(WrongDeviceError);
324         }
325 
326         unsafe {
327             let mut data: *mut ::libc::c_void = ptr::null_mut();
328             let mut stride = 0;
329             let ptr = ffi::gbm_bo_map(
330                 *self.ffi,
331                 x,
332                 y,
333                 width,
334                 height,
335                 ffi::gbm_bo_transfer_flags::GBM_BO_TRANSFER_READ as u32,
336                 &mut stride as *mut _,
337                 &mut data as *mut _,
338             );
339 
340             if ptr.is_null() {
341                 Ok(Err(IoError::last_os_error()))
342             } else {
343                 Ok(Ok(f(&MappedBufferObject {
344                     bo: BORef::Ref(self),
345                     buffer: slice::from_raw_parts_mut(ptr as *mut _, (height * stride) as usize),
346                     data,
347                     stride,
348                     height,
349                     width,
350                     x,
351                     y,
352                 })))
353             }
354         }
355     }
356 
357     /// Map a region of a GBM buffer object for cpu access
358     ///
359     /// This function maps a region of a GBM bo for cpu read/write access.
map_mut<'a, D, F, S>( &'a mut self, device: &Device<D>, x: u32, y: u32, width: u32, height: u32, f: F, ) -> Result<IoResult<S>, WrongDeviceError> where D: AsFd + 'static, F: FnOnce(&mut MappedBufferObject<'a, T>) -> S,360     pub fn map_mut<'a, D, F, S>(
361         &'a mut self,
362         device: &Device<D>,
363         x: u32,
364         y: u32,
365         width: u32,
366         height: u32,
367         f: F,
368     ) -> Result<IoResult<S>, WrongDeviceError>
369     where
370         D: AsFd + 'static,
371         F: FnOnce(&mut MappedBufferObject<'a, T>) -> S,
372     {
373         let device_ref = self._device.upgrade().ok_or(WrongDeviceError)?;
374         if *device_ref != device.as_raw_mut() {
375             // not matching
376             return Err(WrongDeviceError);
377         }
378 
379         unsafe {
380             let mut data: *mut ::libc::c_void = ptr::null_mut();
381             let mut stride = 0;
382             let ptr = ffi::gbm_bo_map(
383                 *self.ffi,
384                 x,
385                 y,
386                 width,
387                 height,
388                 ffi::gbm_bo_transfer_flags::GBM_BO_TRANSFER_READ_WRITE as u32,
389                 &mut stride as *mut _,
390                 &mut data as *mut _,
391             );
392 
393             if ptr.is_null() {
394                 Ok(Err(IoError::last_os_error()))
395             } else {
396                 Ok(Ok(f(&mut MappedBufferObject {
397                     bo: BORef::Mut(self),
398                     buffer: slice::from_raw_parts_mut(ptr as *mut _, (height * stride) as usize),
399                     data,
400                     stride,
401                     height,
402                     width,
403                     x,
404                     y,
405                 })))
406             }
407         }
408     }
409 
410     ///  Write data into the buffer object
411     ///
412     /// If the buffer object was created with the [`BufferObjectFlags::WRITE`] flag,
413     /// this function can be used to write data into the buffer object.  The
414     /// data is copied directly into the object and it's the responsibility
415     /// of the caller to make sure the data represents valid pixel data,
416     /// according to the width, height, stride and format of the buffer object.
write(&mut self, buffer: &[u8]) -> Result<IoResult<()>, DeviceDestroyedError>417     pub fn write(&mut self, buffer: &[u8]) -> Result<IoResult<()>, DeviceDestroyedError> {
418         self._device.upgrade().ok_or(DeviceDestroyedError)?;
419         let result =
420             unsafe { ffi::gbm_bo_write(*self.ffi, buffer.as_ptr() as *const _, buffer.len() as _) };
421         if result != 0 {
422             Ok(Err(IoError::last_os_error()))
423         } else {
424             Ok(Ok(()))
425         }
426     }
427 
428     /// Sets the userdata of the buffer object.
429     ///
430     /// If previously userdata was set, it is returned.
set_userdata(&mut self, userdata: T) -> Result<Option<T>, DeviceDestroyedError>431     pub fn set_userdata(&mut self, userdata: T) -> Result<Option<T>, DeviceDestroyedError> {
432         self._device.upgrade().ok_or(DeviceDestroyedError)?;
433         let old = self.take_userdata();
434 
435         let boxed = Box::new(userdata);
436         unsafe {
437             ffi::gbm_bo_set_user_data(
438                 *self.ffi,
439                 Box::into_raw(boxed) as *mut _,
440                 Some(destroy::<T>),
441             );
442         }
443 
444         old
445     }
446 
447     /// Clears the set userdata of the buffer object.
clear_userdata(&mut self) -> Result<(), DeviceDestroyedError>448     pub fn clear_userdata(&mut self) -> Result<(), DeviceDestroyedError> {
449         self._device.upgrade().ok_or(DeviceDestroyedError)?;
450         let _ = self.take_userdata();
451         Ok(())
452     }
453 
454     /// Returns a reference to set userdata, if any.
userdata(&self) -> Result<Option<&T>, DeviceDestroyedError>455     pub fn userdata(&self) -> Result<Option<&T>, DeviceDestroyedError> {
456         self._device.upgrade().ok_or(DeviceDestroyedError)?;
457         let raw = unsafe { ffi::gbm_bo_get_user_data(*self.ffi) };
458 
459         if raw.is_null() {
460             Ok(None)
461         } else {
462             unsafe { Ok(Some(&*(raw as *mut T))) }
463         }
464     }
465 
466     /// Returns a mutable reference to set userdata, if any.
userdata_mut(&mut self) -> Result<Option<&mut T>, DeviceDestroyedError>467     pub fn userdata_mut(&mut self) -> Result<Option<&mut T>, DeviceDestroyedError> {
468         self._device.upgrade().ok_or(DeviceDestroyedError)?;
469         let raw = unsafe { ffi::gbm_bo_get_user_data(*self.ffi) };
470 
471         if raw.is_null() {
472             Ok(None)
473         } else {
474             unsafe { Ok(Some(&mut *(raw as *mut T))) }
475         }
476     }
477 
478     /// Takes ownership of previously set userdata, if any.
479     ///
480     /// This removes the userdata from the buffer object.
take_userdata(&mut self) -> Result<Option<T>, DeviceDestroyedError>481     pub fn take_userdata(&mut self) -> Result<Option<T>, DeviceDestroyedError> {
482         self._device.upgrade().ok_or(DeviceDestroyedError)?;
483         let raw = unsafe { ffi::gbm_bo_get_user_data(*self.ffi) };
484 
485         if raw.is_null() {
486             Ok(None)
487         } else {
488             unsafe {
489                 let boxed = Box::from_raw(raw as *mut T);
490                 ffi::gbm_bo_set_user_data(*self.ffi, ptr::null_mut(), None);
491                 Ok(Some(*boxed))
492             }
493         }
494     }
495 
new( ffi: *mut ffi::gbm_bo, device: WeakPtr<ffi::gbm_device>, ) -> BufferObject<T>496     pub(crate) unsafe fn new(
497         ffi: *mut ffi::gbm_bo,
498         device: WeakPtr<ffi::gbm_device>,
499     ) -> BufferObject<T> {
500         BufferObject {
501             ffi: Ptr::<ffi::gbm_bo>::new(ffi, |ptr| ffi::gbm_bo_destroy(ptr)),
502             _device: device,
503             _userdata: PhantomData,
504         }
505     }
506 
offsets(&self) -> [u32; 4]507     fn offsets(&self) -> [u32; 4] {
508         let num = self
509             .plane_count()
510             .expect("GbmDevice does not exist anymore");
511         [
512             BufferObject::<T>::offset(self, 0).unwrap(),
513             if num > 1 {
514                 BufferObject::<T>::offset(self, 1).unwrap()
515             } else {
516                 0
517             },
518             if num > 2 {
519                 BufferObject::<T>::offset(self, 2).unwrap()
520             } else {
521                 0
522             },
523             if num > 3 {
524                 BufferObject::<T>::offset(self, 3).unwrap()
525             } else {
526                 0
527             },
528         ]
529     }
530 }
531 
532 impl<T: 'static> AsRaw<ffi::gbm_bo> for BufferObject<T> {
as_raw(&self) -> *const ffi::gbm_bo533     fn as_raw(&self) -> *const ffi::gbm_bo {
534         *self.ffi
535     }
536 }
537 
538 #[cfg(feature = "drm-support")]
539 impl<T: 'static> DrmBuffer for BufferObject<T> {
size(&self) -> (u32, u32)540     fn size(&self) -> (u32, u32) {
541         (
542             self.width().expect("GbmDevice does not exist anymore"),
543             self.height().expect("GbmDevice does not exist anymore"),
544         )
545     }
546 
format(&self) -> Format547     fn format(&self) -> Format {
548         BufferObject::<T>::format(self).expect("GbmDevice does not exist anymore")
549     }
550 
pitch(&self) -> u32551     fn pitch(&self) -> u32 {
552         self.stride().expect("GbmDevice does not exist anymore")
553     }
554 
handle(&self) -> Handle555     fn handle(&self) -> Handle {
556         use std::num::NonZeroU32;
557         unsafe {
558             Handle::from(NonZeroU32::new_unchecked(
559                 self.handle()
560                     .expect("GbmDevice does not exist anymore")
561                     .u32_,
562             ))
563         }
564     }
565 }
566 
567 #[cfg(feature = "drm-support")]
568 impl<T: 'static> DrmPlanarBuffer for BufferObject<T> {
size(&self) -> (u32, u32)569     fn size(&self) -> (u32, u32) {
570         (
571             self.width().expect("GbmDevice does not exist anymore"),
572             self.height().expect("GbmDevice does not exist anymore"),
573         )
574     }
format(&self) -> Format575     fn format(&self) -> Format {
576         BufferObject::<T>::format(self).expect("GbmDevice does not exist anymore")
577     }
modifier(&self) -> Option<Modifier>578     fn modifier(&self) -> Option<Modifier> {
579         Some(BufferObject::<T>::modifier(self).expect("GbmDevice does not exist anymore"))
580     }
pitches(&self) -> [u32; 4]581     fn pitches(&self) -> [u32; 4] {
582         let num = self
583             .plane_count()
584             .expect("GbmDevice does not exist anymore");
585         [
586             BufferObject::<T>::stride_for_plane(self, 0).unwrap(),
587             if num > 1 {
588                 BufferObject::<T>::stride_for_plane(self, 1).unwrap()
589             } else {
590                 0
591             },
592             if num > 2 {
593                 BufferObject::<T>::stride_for_plane(self, 2).unwrap()
594             } else {
595                 0
596             },
597             if num > 3 {
598                 BufferObject::<T>::stride_for_plane(self, 3).unwrap()
599             } else {
600                 0
601             },
602         ]
603     }
handles(&self) -> [Option<Handle>; 4]604     fn handles(&self) -> [Option<Handle>; 4] {
605         use std::num::NonZeroU32;
606         let num = self
607             .plane_count()
608             .expect("GbmDevice does not exist anymore");
609         [
610             Some(unsafe {
611                 Handle::from(NonZeroU32::new_unchecked(
612                     BufferObject::<T>::handle_for_plane(self, 0).unwrap().u32_,
613                 ))
614             }),
615             if num > 1 {
616                 Some(unsafe {
617                     Handle::from(NonZeroU32::new_unchecked(
618                         BufferObject::<T>::handle_for_plane(self, 1).unwrap().u32_,
619                     ))
620                 })
621             } else {
622                 None
623             },
624             if num > 2 {
625                 Some(unsafe {
626                     Handle::from(NonZeroU32::new_unchecked(
627                         BufferObject::<T>::handle_for_plane(self, 2).unwrap().u32_,
628                     ))
629                 })
630             } else {
631                 None
632             },
633             if num > 3 {
634                 Some(unsafe {
635                     Handle::from(NonZeroU32::new_unchecked(
636                         BufferObject::<T>::handle_for_plane(self, 3).unwrap().u32_,
637                     ))
638                 })
639             } else {
640                 None
641             },
642         ]
643     }
offsets(&self) -> [u32; 4]644     fn offsets(&self) -> [u32; 4] {
645         self.offsets()
646     }
647 }
648 
649 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
650 /// Thrown when the GBM device does not belong to the buffer object
651 pub struct WrongDeviceError;
652 
653 impl fmt::Display for WrongDeviceError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result654     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
655         write!(
656             f,
657             "The gbm device specified is not the one this buffer object belongs to"
658         )
659     }
660 }
661 
662 impl error::Error for WrongDeviceError {}
663 
664 /// Thrown when the fd is invalid
665 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
666 pub struct InvalidFdError;
667 
668 impl fmt::Display for InvalidFdError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result669     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
670         write!(f, "The returned fd is invalid")
671     }
672 }
673 
674 impl error::Error for InvalidFdError {}
675 
676 /// Thrown when an error occurs during getting a bo fd
677 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
678 pub enum FdError {
679     /// The underlying device has been destroyed
680     DeviceDestroyed(DeviceDestroyedError),
681     /// The operation returned an invalid fd
682     InvalidFd(InvalidFdError),
683 }
684 
685 impl From<DeviceDestroyedError> for FdError {
from(err: DeviceDestroyedError) -> Self686     fn from(err: DeviceDestroyedError) -> Self {
687         FdError::DeviceDestroyed(err)
688     }
689 }
690 
691 impl From<InvalidFdError> for FdError {
from(err: InvalidFdError) -> Self692     fn from(err: InvalidFdError) -> Self {
693         FdError::InvalidFd(err)
694     }
695 }
696 
697 impl fmt::Display for FdError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result698     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
699         match self {
700             FdError::DeviceDestroyed(err) => err.fmt(f),
701             FdError::InvalidFd(err) => err.fmt(f),
702         }
703     }
704 }
705 
706 impl error::Error for FdError {
source(&self) -> Option<&(dyn error::Error + 'static)>707     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
708         match self {
709             FdError::DeviceDestroyed(err) => Some(err),
710             FdError::InvalidFd(err) => Some(err),
711         }
712     }
713 }
714