|
|
|
@ -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 {
|
|
|
|
|