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