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