use std::{ffi::OsString, os::fd::{AsRawFd, OwnedFd}}; use crate::uapi::i915::DrmGemHandle; use super::super::uapi; use std::path::Path; use std::fs::File; pub use uapi::i915::GemIoctlError; #[derive(Debug)] pub struct DrmDeviceNode { pub fd: OwnedFd, pub path: Option, } #[derive(Debug)] pub struct GemHandle<'a> { pub handle: DrmGemHandle, pub node: &'a DrmDeviceNode, } /// An owned GEM handle that will be closed when dropped impl GemHandle<'_> { pub fn new(node: &DrmDeviceNode, size: u64) -> Option { uapi::i915::make_gem(node.fd.as_raw_fd(), size).map(|handle| GemHandle { handle: handle, node: &node, }) } pub fn from_handle(node: &DrmDeviceNode, handle: DrmGemHandle) -> Result { // Avoid invoking GemHandle::is_valid() here to prevent the drop() method from trying to drop an invalid handle let is_valid = uapi::i915::gem_is_valid(node.fd.as_raw_fd(), &handle); if is_valid.is_ok() && is_valid.unwrap() { let res = GemHandle { handle: handle, node: &node, }; return Ok(res); } else { return Err(is_valid.err().unwrap_or(GemIoctlError::InvalidHandle)); } } pub fn close(self) -> Result<(), i32> { return unsafe { uapi::i915::close_gem_ref(self.node.fd.as_raw_fd(), &self.handle) }; } pub fn has_tiling(&self) -> Result { uapi::i915::gem_has_tiling(self.node.fd.as_raw_fd(), &self.handle) } pub fn is_valid(&self) -> Result { uapi::i915::gem_is_valid(self.node.fd.as_raw_fd(), &self.handle) } } impl Drop for GemHandle<'_> { fn drop(&mut self) { // Ignoring the close failing as an invalid Gem handle's drop is a no-op _ = unsafe { uapi::i915::close_gem_ref(self.node.fd.as_raw_fd(), &self.handle) }; } } #[derive(Debug)] pub struct Device { pub node: DrmDeviceNode, pub driver: uapi::DrmVersion, } #[derive(Debug)] pub struct Engine { pub info: uapi::i915::EngineInfo, } pub fn find_device() -> Option { uapi::i915::find_node().and_then(|file| Device::from_path(file.path?)) } impl Device { pub fn from_fd(fd: OwnedFd) -> Option { let driver = uapi::get_drm_version(fd.as_raw_fd())?; Some(Device { node: DrmDeviceNode { fd: fd, path: None, }, driver: driver, }) } pub fn from_path(path: OsString) -> Option { let file = File::open(Path::new(&path)).ok()?; let driver = uapi::get_drm_version(file.as_raw_fd())?; Some(Device { node: DrmDeviceNode { fd: OwnedFd::from(file), path: Some(path), }, driver: driver, }) } pub fn get_engines(&self) -> Option> { uapi::i915::get_engines(self.node.fd.as_raw_fd()).map(|engines| { engines.into_iter().map(|engine_info| { Engine { info: engine_info, } }).collect() }) } pub fn get_param(&self, param: u32) -> Option { uapi::i915::get_param(self.node.fd.as_raw_fd(), param as i32) } }