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