|  |  |  | @ -29,6 +29,11 @@ pub struct EngineInfo { | 
			
		
	
		
			
				
					|  |  |  |  |     pub capabilities: u64, | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 
			
		
	
		
			
				
					|  |  |  |  | pub struct DrmGemHandle { | 
			
		
	
		
			
				
					|  |  |  |  |     pub handle: u32, | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | fn engine_class_from_u16(engine_class: u16) -> EngineClass { | 
			
		
	
		
			
				
					|  |  |  |  |     match engine_class { | 
			
		
	
		
			
				
					|  |  |  |  |         0 => EngineClass::Render, | 
			
		
	
	
		
			
				
					|  |  |  | @ -83,32 +88,39 @@ impl EngineInfo { | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub unsafe fn do_query<T>(fd: RawFd, query_id: u32) -> Option<*mut T> { | 
			
		
	
		
			
				
					|  |  |  |  |     let mut query_item = native::drm_i915_query_item { | 
			
		
	
		
			
				
					|  |  |  |  |         query_id: query_id as u64, | 
			
		
	
		
			
				
					|  |  |  |  |         length: 0, | 
			
		
	
		
			
				
					|  |  |  |  |         data_ptr: core::ptr::null_mut::<c_void>() as u64, | 
			
		
	
		
			
				
					|  |  |  |  |         flags: 0, | 
			
		
	
		
			
				
					|  |  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  |  |     let mut query = native::drm_i915_query { | 
			
		
	
		
			
				
					|  |  |  |  |         items_ptr: (&mut query_item) as *mut native::drm_i915_query_item as u64, | 
			
		
	
		
			
				
					|  |  |  |  |         num_items: 1, | 
			
		
	
		
			
				
					|  |  |  |  |         flags: 0, | 
			
		
	
		
			
				
					|  |  |  |  |     }; | 
			
		
	
		
			
				
					|  |  |  |  |     let res = libc::ioctl(fd.as_raw_fd(), native::DRM_IOCTL_I915_QUERY, &mut query); | 
			
		
	
		
			
				
					|  |  |  |  |     if res != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |         return None; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     let result_info = libc::malloc(query_item.length as usize) | 
			
		
	
		
			
				
					|  |  |  |  |         as *mut T; | 
			
		
	
		
			
				
					|  |  |  |  |     libc::memset(result_info as *mut c_void, 0, query_item.length as usize); | 
			
		
	
		
			
				
					|  |  |  |  |     query_item.data_ptr = result_info as u64; | 
			
		
	
		
			
				
					|  |  |  |  |     let res = libc::ioctl(fd.as_raw_fd(), native::DRM_IOCTL_I915_QUERY, &mut query); | 
			
		
	
		
			
				
					|  |  |  |  |     if res != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |         return None; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     Some(result_info) | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub fn get_engines(fd: RawFd) -> Option<Vec<EngineInfo>> { | 
			
		
	
		
			
				
					|  |  |  |  |     unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |         let mut query_item = native::drm_i915_query_item { | 
			
		
	
		
			
				
					|  |  |  |  |             query_id: native::DRM_I915_QUERY_ENGINE_INFO as u64, | 
			
		
	
		
			
				
					|  |  |  |  |             length: 0, | 
			
		
	
		
			
				
					|  |  |  |  |             data_ptr: core::ptr::null_mut::<c_void>() as u64, | 
			
		
	
		
			
				
					|  |  |  |  |             flags: 0, | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         let mut query = native::drm_i915_query { | 
			
		
	
		
			
				
					|  |  |  |  |             items_ptr: (&mut query_item) as *mut native::drm_i915_query_item as u64, | 
			
		
	
		
			
				
					|  |  |  |  |             num_items: 1, | 
			
		
	
		
			
				
					|  |  |  |  |             flags: 0, | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         let res = libc::ioctl(fd.as_raw_fd(), native::DRM_IOCTL_I915_QUERY, &mut query); | 
			
		
	
		
			
				
					|  |  |  |  |         if res != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |             return None; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         let engine_info = libc::malloc(query_item.length as usize) | 
			
		
	
		
			
				
					|  |  |  |  |             as *mut native::drm_i915_query_engine_info; | 
			
		
	
		
			
				
					|  |  |  |  |         libc::memset(engine_info as *mut c_void, 0, query_item.length as usize); | 
			
		
	
		
			
				
					|  |  |  |  |         query_item.data_ptr = engine_info as u64; | 
			
		
	
		
			
				
					|  |  |  |  |         let res = libc::ioctl(fd.as_raw_fd(), native::DRM_IOCTL_I915_QUERY, &mut query); | 
			
		
	
		
			
				
					|  |  |  |  |         if res != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |             return None; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         let engine_data = engine_info.as_mut().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |         let engine_data = 
 | 
			
		
	
		
			
				
					|  |  |  |  |             do_query::<native::drm_i915_query_engine_info>(fd, 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 native::DRM_I915_QUERY_ENGINE_INFO)? | 
			
		
	
		
			
				
					|  |  |  |  |             .as_mut().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |         let engines = engine_data.engines.as_mut_slice(engine_data.num_engines as usize); | 
			
		
	
		
			
				
					|  |  |  |  |         let mut engines_res: Vec<EngineInfo> = Vec::new(); | 
			
		
	
		
			
				
					|  |  |  |  |         for i in 0..engine_data.num_engines { | 
			
		
	
	
		
			
				
					|  |  |  | @ -134,6 +146,94 @@ pub fn get_param(fd: RawFd, param_id: i32) -> Option<i32> { | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub fn get_context_param(fd: RawFd, context_id: u32, param_id: u32) -> Option<u64> { | 
			
		
	
		
			
				
					|  |  |  |  |     unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |         let mut param = native::drm_i915_gem_context_param { | 
			
		
	
		
			
				
					|  |  |  |  |             ctx_id: context_id, | 
			
		
	
		
			
				
					|  |  |  |  |             param: param_id as u64, | 
			
		
	
		
			
				
					|  |  |  |  |             value: 0, | 
			
		
	
		
			
				
					|  |  |  |  |             size: 0, | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         let res = libc::ioctl(fd, native::DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &mut param); | 
			
		
	
		
			
				
					|  |  |  |  |         if res != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |             return None; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Some(param.value) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub fn make_gem(fd: RawFd, size: u64) -> Option<DrmGemHandle> { | 
			
		
	
		
			
				
					|  |  |  |  |     unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |         let mut create = native::drm_i915_gem_create { | 
			
		
	
		
			
				
					|  |  |  |  |             size: size, | 
			
		
	
		
			
				
					|  |  |  |  |             handle: 0, | 
			
		
	
		
			
				
					|  |  |  |  |             pad: 0, | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         let res = libc::ioctl(fd, native::DRM_IOCTL_I915_GEM_CREATE, &mut create); | 
			
		
	
		
			
				
					|  |  |  |  |         if res != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |             return None; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         let handle = DrmGemHandle { | 
			
		
	
		
			
				
					|  |  |  |  |             handle: create.handle, | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         Some(handle) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub fn close_gem(fd: RawFd, handle: DrmGemHandle) -> Result<(), i32> { | 
			
		
	
		
			
				
					|  |  |  |  |     unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |         let mut close = native::drm_gem_close { | 
			
		
	
		
			
				
					|  |  |  |  |             handle: handle.handle, | 
			
		
	
		
			
				
					|  |  |  |  |             pad: 0, | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         let res = libc::ioctl(fd, native::DRM_IOCTL_GEM_CLOSE, &mut close); | 
			
		
	
		
			
				
					|  |  |  |  |         if res != 0 { | 
			
		
	
		
			
				
					|  |  |  |  |             return Err(res); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Ok(()) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 
			
		
	
		
			
				
					|  |  |  |  | pub enum GemIoctlError { | 
			
		
	
		
			
				
					|  |  |  |  |     InvalidHandle, | 
			
		
	
		
			
				
					|  |  |  |  |     PermissionDenied, | 
			
		
	
		
			
				
					|  |  |  |  |     Unknown(i32), | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub fn gem_has_tiling(fd: RawFd, handle: DrmGemHandle) -> Result<bool, GemIoctlError> { | 
			
		
	
		
			
				
					|  |  |  |  |     unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |         let mut tiling = native::drm_i915_gem_set_tiling { | 
			
		
	
		
			
				
					|  |  |  |  |             handle: handle.handle, | 
			
		
	
		
			
				
					|  |  |  |  |             tiling_mode: 0, | 
			
		
	
		
			
				
					|  |  |  |  |             stride: 0, | 
			
		
	
		
			
				
					|  |  |  |  |             swizzle_mode: 0, | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         let res = libc::ioctl(fd, native::DRM_IOCTL_I915_GEM_SET_TILING, &mut tiling); | 
			
		
	
		
			
				
					|  |  |  |  |         match -res { | 
			
		
	
		
			
				
					|  |  |  |  |             0 => Ok(true), | 
			
		
	
		
			
				
					|  |  |  |  |             libc::ENOENT => Err(GemIoctlError::InvalidHandle), | 
			
		
	
		
			
				
					|  |  |  |  |             libc::EPERM => Err(GemIoctlError::PermissionDenied), | 
			
		
	
		
			
				
					|  |  |  |  |             libc::EINVAL => Ok(false), | 
			
		
	
		
			
				
					|  |  |  |  |             _ => Err(GemIoctlError::Unknown(res)), | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub fn gem_is_valid(fd: RawFd, handle: DrmGemHandle) -> Result<bool, GemIoctlError> { | 
			
		
	
		
			
				
					|  |  |  |  |     let res = gem_has_tiling(fd, handle); | 
			
		
	
		
			
				
					|  |  |  |  |     if res.is_ok() && res.unwrap() { | 
			
		
	
		
			
				
					|  |  |  |  |         return Ok(true); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // For some reason the kernel returns -EPERM instead of -ENOENT when the handle is invalid...
 | 
			
		
	
		
			
				
					|  |  |  |  |     if res.is_err() && res.unwrap_err() == GemIoctlError::PermissionDenied { | 
			
		
	
		
			
				
					|  |  |  |  |         return Ok(false); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     return Err(res.unwrap_err()); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub fn find_node() -> Option<DrmDeviceNode> { | 
			
		
	
		
			
				
					|  |  |  |  |     let inodes = fs::read_dir("/dev/dri").ok()?; | 
			
		
	
		
			
				
					|  |  |  |  |     for inode in inodes { | 
			
		
	
	
		
			
				
					|  |  |  | 
 |