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, 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> { |
23 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
24 | f&mut DebugStruct<'_, '_>.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(name:"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> { |
85 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
86 | f&mut DebugStruct<'_, '_>.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 | name:"buffer" , |
96 | value:match &self.bo { |
97 | BORef::Ref(bo: &&BufferObject) => *bo, |
98 | BORef::Mut(bo: &&mut BufferObject) => *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. |
109 | pub fn stride(&self) -> u32 { |
110 | self.stride |
111 | } |
112 | |
113 | /// The height of the mapped region for the buffer |
114 | pub fn height(&self) -> u32 { |
115 | self.height |
116 | } |
117 | |
118 | /// The width of the mapped region for the buffer |
119 | 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 |
124 | 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 |
129 | pub fn y(&self) -> u32 { |
130 | self.y |
131 | } |
132 | |
133 | /// Access to the underlying image buffer |
134 | pub fn buffer(&self) -> &[u8] { |
135 | self.buffer |
136 | } |
137 | |
138 | /// Mutable access to the underlying image buffer |
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>; |
146 | fn deref(&self) -> &BufferObject<T> { |
147 | match &self.bo { |
148 | BORef::Ref(bo: &&BufferObject) => bo, |
149 | BORef::Mut(bo: &&mut BufferObject) => bo, |
150 | } |
151 | } |
152 | } |
153 | |
154 | impl<'a, T: 'static> DerefMut for MappedBufferObject<'a, T> { |
155 | fn deref_mut(&mut self) -> &mut BufferObject<T> { |
156 | match &mut self.bo { |
157 | BORef::Ref(_) => unreachable!(), |
158 | BORef::Mut(bo: &mut &mut BufferObject) => bo, |
159 | } |
160 | } |
161 | } |
162 | |
163 | impl<'a, T: 'static> Drop for MappedBufferObject<'a, T> { |
164 | fn drop(&mut self) { |
165 | let ffi: &Ptr<{unknown}> = match &self.bo { |
166 | BORef::Ref(bo: &&BufferObject) => &bo.ffi, |
167 | BORef::Mut(bo: &&mut BufferObject) => &bo.ffi, |
168 | }; |
169 | unsafe { ffi::gbm_bo_unmap(**ffi, self.data) } |
170 | } |
171 | } |
172 | |
173 | unsafe extern "C" fn destroy<T: 'static>(_: *mut ffi::gbm_bo, ptr: *mut ::libc::c_void) { |
174 | let ptr: *mut T = 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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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. |
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 handle of the buffer object |
260 | /// |
261 | /// This is stored in the platform generic union [`BufferObjectHandle`] type. However |
262 | /// the format of this handle is platform specific. |
263 | pub fn handle(&self) -> Result<BufferObjectHandle, DeviceDestroyedError> { |
264 | self._device.upgrade().ok_or(DeviceDestroyedError)?; |
265 | Ok(unsafe { ffi::gbm_bo_get_handle(*self.ffi) }) |
266 | } |
267 | |
268 | /// Get a DMA-BUF file descriptor for a plane of the buffer object |
269 | /// |
270 | /// This function creates a DMA-BUF (also known as PRIME) file descriptor |
271 | /// handle for a plane of the buffer object. Each call to [`Self::fd_for_plane()`] |
272 | /// returns a new file descriptor and the caller is responsible for closing |
273 | /// the file descriptor. |
274 | pub fn fd_for_plane(&self, plane: i32) -> Result<OwnedFd, FdError> { |
275 | self._device.upgrade().ok_or(DeviceDestroyedError)?; |
276 | unsafe { |
277 | let fd = ffi::gbm_bo_get_fd_for_plane(*self.ffi, plane); |
278 | |
279 | if fd == -1 { |
280 | return Err(InvalidFdError.into()); |
281 | } |
282 | |
283 | Ok(OwnedFd::from_raw_fd(fd)) |
284 | } |
285 | } |
286 | |
287 | /// Get the handle of a plane of the buffer object |
288 | /// |
289 | /// This is stored in the platform generic union [`BufferObjectHandle`] type. However |
290 | /// the format of this handle is platform specific. |
291 | pub fn handle_for_plane(&self, plane: i32) -> Result<BufferObjectHandle, DeviceDestroyedError> { |
292 | self._device.upgrade().ok_or(DeviceDestroyedError)?; |
293 | Ok(unsafe { ffi::gbm_bo_get_handle_for_plane(*self.ffi, plane) }) |
294 | } |
295 | |
296 | /// Map a region of a GBM buffer object for cpu access |
297 | /// |
298 | /// This function maps a region of a GBM bo for cpu read access. |
299 | pub fn map<'a, D, F, S>( |
300 | &'a self, |
301 | device: &Device<D>, |
302 | x: u32, |
303 | y: u32, |
304 | width: u32, |
305 | height: u32, |
306 | f: F, |
307 | ) -> Result<IoResult<S>, WrongDeviceError> |
308 | where |
309 | D: AsFd + 'static, |
310 | F: FnOnce(&MappedBufferObject<'a, T>) -> S, |
311 | { |
312 | let device_ref = self._device.upgrade().ok_or(WrongDeviceError)?; |
313 | if *device_ref != device.as_raw_mut() { |
314 | // not matching |
315 | return Err(WrongDeviceError); |
316 | } |
317 | |
318 | unsafe { |
319 | let mut data: *mut ::libc::c_void = ptr::null_mut(); |
320 | let mut stride = 0; |
321 | let ptr = ffi::gbm_bo_map( |
322 | *self.ffi, |
323 | x, |
324 | y, |
325 | width, |
326 | height, |
327 | ffi::gbm_bo_transfer_flags::GBM_BO_TRANSFER_READ as u32, |
328 | &mut stride as *mut _, |
329 | &mut data as *mut _, |
330 | ); |
331 | |
332 | if ptr.is_null() { |
333 | Ok(Err(IoError::last_os_error())) |
334 | } else { |
335 | Ok(Ok(f(&MappedBufferObject { |
336 | bo: BORef::Ref(self), |
337 | buffer: slice::from_raw_parts_mut(ptr as *mut _, (height * stride) as usize), |
338 | data, |
339 | stride, |
340 | height, |
341 | width, |
342 | x, |
343 | y, |
344 | }))) |
345 | } |
346 | } |
347 | } |
348 | |
349 | /// Map a region of a GBM buffer object for cpu access |
350 | /// |
351 | /// This function maps a region of a GBM bo for cpu read/write access. |
352 | pub fn map_mut<'a, D, F, S>( |
353 | &'a mut self, |
354 | device: &Device<D>, |
355 | x: u32, |
356 | y: u32, |
357 | width: u32, |
358 | height: u32, |
359 | f: F, |
360 | ) -> Result<IoResult<S>, WrongDeviceError> |
361 | where |
362 | D: AsFd + 'static, |
363 | F: FnOnce(&mut MappedBufferObject<'a, T>) -> S, |
364 | { |
365 | let device_ref = self._device.upgrade().ok_or(WrongDeviceError)?; |
366 | if *device_ref != device.as_raw_mut() { |
367 | // not matching |
368 | return Err(WrongDeviceError); |
369 | } |
370 | |
371 | unsafe { |
372 | let mut data: *mut ::libc::c_void = ptr::null_mut(); |
373 | let mut stride = 0; |
374 | let ptr = ffi::gbm_bo_map( |
375 | *self.ffi, |
376 | x, |
377 | y, |
378 | width, |
379 | height, |
380 | ffi::gbm_bo_transfer_flags::GBM_BO_TRANSFER_READ_WRITE as u32, |
381 | &mut stride as *mut _, |
382 | &mut data as *mut _, |
383 | ); |
384 | |
385 | if ptr.is_null() { |
386 | Ok(Err(IoError::last_os_error())) |
387 | } else { |
388 | Ok(Ok(f(&mut MappedBufferObject { |
389 | bo: BORef::Mut(self), |
390 | buffer: slice::from_raw_parts_mut(ptr as *mut _, (height * stride) as usize), |
391 | data, |
392 | stride, |
393 | height, |
394 | width, |
395 | x, |
396 | y, |
397 | }))) |
398 | } |
399 | } |
400 | } |
401 | |
402 | /// Write data into the buffer object |
403 | /// |
404 | /// If the buffer object was created with the [`BufferObjectFlags::WRITE`] flag, |
405 | /// this function can be used to write data into the buffer object. The |
406 | /// data is copied directly into the object and it's the responsibility |
407 | /// of the caller to make sure the data represents valid pixel data, |
408 | /// according to the width, height, stride and format of the buffer object. |
409 | pub fn write(&mut self, buffer: &[u8]) -> Result<IoResult<()>, DeviceDestroyedError> { |
410 | self._device.upgrade().ok_or(DeviceDestroyedError)?; |
411 | let result = |
412 | unsafe { ffi::gbm_bo_write(*self.ffi, buffer.as_ptr() as *const _, buffer.len() as _) }; |
413 | if result != 0 { |
414 | Ok(Err(IoError::last_os_error())) |
415 | } else { |
416 | Ok(Ok(())) |
417 | } |
418 | } |
419 | |
420 | /// Sets the userdata of the buffer object. |
421 | /// |
422 | /// If previously userdata was set, it is returned. |
423 | pub fn set_userdata(&mut self, userdata: T) -> Result<Option<T>, DeviceDestroyedError> { |
424 | self._device.upgrade().ok_or(DeviceDestroyedError)?; |
425 | let old = self.take_userdata(); |
426 | |
427 | let boxed = Box::new(userdata); |
428 | unsafe { |
429 | ffi::gbm_bo_set_user_data( |
430 | *self.ffi, |
431 | Box::into_raw(boxed) as *mut _, |
432 | Some(destroy::<T>), |
433 | ); |
434 | } |
435 | |
436 | old |
437 | } |
438 | |
439 | /// Clears the set userdata of the buffer object. |
440 | pub fn clear_userdata(&mut self) -> Result<(), DeviceDestroyedError> { |
441 | self._device.upgrade().ok_or(DeviceDestroyedError)?; |
442 | let _ = self.take_userdata(); |
443 | Ok(()) |
444 | } |
445 | |
446 | /// Returns a reference to set userdata, if any. |
447 | pub fn userdata(&self) -> Result<Option<&T>, DeviceDestroyedError> { |
448 | self._device.upgrade().ok_or(DeviceDestroyedError)?; |
449 | let raw = unsafe { ffi::gbm_bo_get_user_data(*self.ffi) }; |
450 | |
451 | if raw.is_null() { |
452 | Ok(None) |
453 | } else { |
454 | unsafe { Ok(Some(&*(raw as *mut T))) } |
455 | } |
456 | } |
457 | |
458 | /// Returns a mutable reference to set userdata, if any. |
459 | pub fn userdata_mut(&mut self) -> Result<Option<&mut T>, DeviceDestroyedError> { |
460 | self._device.upgrade().ok_or(DeviceDestroyedError)?; |
461 | let raw = unsafe { ffi::gbm_bo_get_user_data(*self.ffi) }; |
462 | |
463 | if raw.is_null() { |
464 | Ok(None) |
465 | } else { |
466 | unsafe { Ok(Some(&mut *(raw as *mut T))) } |
467 | } |
468 | } |
469 | |
470 | /// Takes ownership of previously set userdata, if any. |
471 | /// |
472 | /// This removes the userdata from the buffer object. |
473 | pub fn take_userdata(&mut self) -> Result<Option<T>, DeviceDestroyedError> { |
474 | self._device.upgrade().ok_or(DeviceDestroyedError)?; |
475 | let raw = unsafe { ffi::gbm_bo_get_user_data(*self.ffi) }; |
476 | |
477 | if raw.is_null() { |
478 | Ok(None) |
479 | } else { |
480 | unsafe { |
481 | let boxed = Box::from_raw(raw as *mut T); |
482 | ffi::gbm_bo_set_user_data(*self.ffi, ptr::null_mut(), None); |
483 | Ok(Some(*boxed)) |
484 | } |
485 | } |
486 | } |
487 | |
488 | pub(crate) unsafe fn new( |
489 | ffi: *mut ffi::gbm_bo, |
490 | device: WeakPtr<ffi::gbm_device>, |
491 | ) -> BufferObject<T> { |
492 | BufferObject { |
493 | ffi: Ptr::<ffi::gbm_bo>::new(ffi, |ptr| ffi::gbm_bo_destroy(ptr)), |
494 | _device: device, |
495 | _userdata: PhantomData, |
496 | } |
497 | } |
498 | } |
499 | |
500 | impl<T: 'static> AsRaw<ffi::gbm_bo> for BufferObject<T> { |
501 | fn as_raw(&self) -> *const ffi::gbm_bo { |
502 | *self.ffi |
503 | } |
504 | } |
505 | |
506 | #[cfg (feature = "drm-support" )] |
507 | impl<T: 'static> DrmBuffer for BufferObject<T> { |
508 | fn size(&self) -> (u32, u32) { |
509 | ( |
510 | self.width().expect("GbmDevice does not exist anymore" ), |
511 | self.height().expect("GbmDevice does not exist anymore" ), |
512 | ) |
513 | } |
514 | |
515 | fn format(&self) -> Format { |
516 | BufferObject::<T>::format(self).expect("GbmDevice does not exist anymore" ) |
517 | } |
518 | |
519 | fn pitch(&self) -> u32 { |
520 | self.stride().expect("GbmDevice does not exist anymore" ) |
521 | } |
522 | |
523 | fn handle(&self) -> Handle { |
524 | use std::num::NonZeroU32; |
525 | unsafe { |
526 | Handle::from(NonZeroU32::new_unchecked( |
527 | self.handle() |
528 | .expect("GbmDevice does not exist anymore" ) |
529 | .u32_, |
530 | )) |
531 | } |
532 | } |
533 | } |
534 | |
535 | #[cfg (feature = "drm-support" )] |
536 | impl<T: 'static> DrmPlanarBuffer for BufferObject<T> { |
537 | fn size(&self) -> (u32, u32) { |
538 | ( |
539 | self.width().expect("GbmDevice does not exist anymore" ), |
540 | self.height().expect("GbmDevice does not exist anymore" ), |
541 | ) |
542 | } |
543 | fn format(&self) -> Format { |
544 | BufferObject::<T>::format(self).expect("GbmDevice does not exist anymore" ) |
545 | } |
546 | fn pitches(&self) -> [u32; 4] { |
547 | let num = self |
548 | .plane_count() |
549 | .expect("GbmDevice does not exist anymore" ); |
550 | [ |
551 | BufferObject::<T>::stride_for_plane(self, 0).unwrap(), |
552 | if num > 1 { |
553 | BufferObject::<T>::stride_for_plane(self, 1).unwrap() |
554 | } else { |
555 | 0 |
556 | }, |
557 | if num > 2 { |
558 | BufferObject::<T>::stride_for_plane(self, 2).unwrap() |
559 | } else { |
560 | 0 |
561 | }, |
562 | if num > 3 { |
563 | BufferObject::<T>::stride_for_plane(self, 3).unwrap() |
564 | } else { |
565 | 0 |
566 | }, |
567 | ] |
568 | } |
569 | fn handles(&self) -> [Option<Handle>; 4] { |
570 | use std::num::NonZeroU32; |
571 | let num = self |
572 | .plane_count() |
573 | .expect("GbmDevice does not exist anymore" ); |
574 | [ |
575 | Some(unsafe { |
576 | Handle::from(NonZeroU32::new_unchecked( |
577 | BufferObject::<T>::handle_for_plane(self, 0).unwrap().u32_, |
578 | )) |
579 | }), |
580 | if num > 1 { |
581 | Some(unsafe { |
582 | Handle::from(NonZeroU32::new_unchecked( |
583 | BufferObject::<T>::handle_for_plane(self, 1).unwrap().u32_, |
584 | )) |
585 | }) |
586 | } else { |
587 | None |
588 | }, |
589 | if num > 2 { |
590 | Some(unsafe { |
591 | Handle::from(NonZeroU32::new_unchecked( |
592 | BufferObject::<T>::handle_for_plane(self, 2).unwrap().u32_, |
593 | )) |
594 | }) |
595 | } else { |
596 | None |
597 | }, |
598 | if num > 3 { |
599 | Some(unsafe { |
600 | Handle::from(NonZeroU32::new_unchecked( |
601 | BufferObject::<T>::handle_for_plane(self, 3).unwrap().u32_, |
602 | )) |
603 | }) |
604 | } else { |
605 | None |
606 | }, |
607 | ] |
608 | } |
609 | fn offsets(&self) -> [u32; 4] { |
610 | let num = self |
611 | .plane_count() |
612 | .expect("GbmDevice does not exist anymore" ); |
613 | [ |
614 | BufferObject::<T>::offset(self, 0).unwrap(), |
615 | if num > 1 { |
616 | BufferObject::<T>::offset(self, 1).unwrap() |
617 | } else { |
618 | 0 |
619 | }, |
620 | if num > 2 { |
621 | BufferObject::<T>::offset(self, 2).unwrap() |
622 | } else { |
623 | 0 |
624 | }, |
625 | if num > 3 { |
626 | BufferObject::<T>::offset(self, 3).unwrap() |
627 | } else { |
628 | 0 |
629 | }, |
630 | ] |
631 | } |
632 | } |
633 | |
634 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
635 | /// Thrown when the GBM device does not belong to the buffer object |
636 | pub struct WrongDeviceError; |
637 | |
638 | impl fmt::Display for WrongDeviceError { |
639 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
640 | write!( |
641 | f, |
642 | "The gbm device specified is not the one this buffer object belongs to" |
643 | ) |
644 | } |
645 | } |
646 | |
647 | impl error::Error for WrongDeviceError {} |
648 | |
649 | /// Thrown when the fd is invalid |
650 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
651 | pub struct InvalidFdError; |
652 | |
653 | impl fmt::Display for InvalidFdError { |
654 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
655 | write!(f, "The returned fd is invalid" ) |
656 | } |
657 | } |
658 | |
659 | impl error::Error for InvalidFdError {} |
660 | |
661 | /// Thrown when an error occurs during getting a bo fd |
662 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
663 | pub enum FdError { |
664 | /// The underlying device has been destroyed |
665 | DeviceDestroyed(DeviceDestroyedError), |
666 | /// The operation returned an invalid fd |
667 | InvalidFd(InvalidFdError), |
668 | } |
669 | |
670 | impl From<DeviceDestroyedError> for FdError { |
671 | fn from(err: DeviceDestroyedError) -> Self { |
672 | FdError::DeviceDestroyed(err) |
673 | } |
674 | } |
675 | |
676 | impl From<InvalidFdError> for FdError { |
677 | fn from(err: InvalidFdError) -> Self { |
678 | FdError::InvalidFd(err) |
679 | } |
680 | } |
681 | |
682 | impl fmt::Display for FdError { |
683 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
684 | match self { |
685 | FdError::DeviceDestroyed(err: &DeviceDestroyedError) => err.fmt(f), |
686 | FdError::InvalidFd(err: &InvalidFdError) => err.fmt(f), |
687 | } |
688 | } |
689 | } |
690 | |
691 | impl error::Error for FdError { |
692 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { |
693 | match self { |
694 | FdError::DeviceDestroyed(err: &DeviceDestroyedError) => Some(err), |
695 | FdError::InvalidFd(err: &InvalidFdError) => Some(err), |
696 | } |
697 | } |
698 | } |
699 | |