From ca3f6c4d6005b0589602c17de02a30f680dd6077 Mon Sep 17 00:00:00 2001 From: itycodes Date: Sun, 3 Nov 2024 21:09:39 +0100 Subject: [PATCH] Initial commit --- .cargo/config.toml | 0 .gitignore | 1 + Cargo.lock | 306 ++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 15 ++ build.rs | 15 ++ clib/wrapper.h | 14 ++ src/gpu/drm_i915/mod.rs | 61 ++++++++ src/gpu/mod.rs | 1 + src/lib.rs | 3 + src/native/mod.rs | 4 + src/uapi/mod.rs | 209 +++++++++++++++++++++++++++ tests/tests_i915_gpu.rs | 70 +++++++++ tests/tests_raw.rs | 66 +++++++++ tests/tests_uapi.rs | 20 +++ 14 files changed, 785 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 build.rs create mode 100644 clib/wrapper.h create mode 100644 src/gpu/drm_i915/mod.rs create mode 100644 src/gpu/mod.rs create mode 100644 src/lib.rs create mode 100644 src/native/mod.rs create mode 100644 src/uapi/mod.rs create mode 100644 tests/tests_i915_gpu.rs create mode 100644 tests/tests_raw.rs create mode 100644 tests/tests_uapi.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..d068933 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,306 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "intel_gpu_uapi" +version = "0.1.0" +dependencies = [ + "bindgen", + "libc", + "nix", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "prettyplease" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9341d37 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "intel_gpu_uapi" +version = "0.1.0" +edition = "2021" + +[dependencies] +libc = "0.2.161" + +[build-dependencies] +bindgen = "0.70.1" + +[dev-dependencies] +libc = "0.2.161" +nix = { version = "0.29.0", features = ["fs"] } + diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..3efd46e --- /dev/null +++ b/build.rs @@ -0,0 +1,15 @@ +use std::env; +use std::path::PathBuf; + +fn main() { + let bindings = bindgen::Builder::default() + .header("clib/wrapper.h") + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .generate() + .expect("Unable to generate bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +} diff --git a/clib/wrapper.h b/clib/wrapper.h new file mode 100644 index 0000000..9f907bb --- /dev/null +++ b/clib/wrapper.h @@ -0,0 +1,14 @@ +#include +#include + +const __u64 _DRM_IOCTL_VERSION = DRM_IOCTL_VERSION; +#undef DRM_IOCTL_VERSION +const __u64 DRM_IOCTL_VERSION = _DRM_IOCTL_VERSION; + +const __u64 _DRM_IOCTL_I915_QUERY = DRM_IOCTL_I915_QUERY; +#undef DRM_IOCTL_I915_QUERY +const __u64 DRM_IOCTL_I915_QUERY = _DRM_IOCTL_I915_QUERY; + +const __u64 _DRM_IOCTL_I915_GETPARAM = DRM_IOCTL_I915_GETPARAM; +#undef DRM_IOCTL_I915_GETPARAM +const __u64 DRM_IOCTL_I915_GETPARAM = _DRM_IOCTL_I915_GETPARAM; \ No newline at end of file diff --git a/src/gpu/drm_i915/mod.rs b/src/gpu/drm_i915/mod.rs new file mode 100644 index 0000000..a26b4fa --- /dev/null +++ b/src/gpu/drm_i915/mod.rs @@ -0,0 +1,61 @@ +use std::{ffi::OsString, os::fd::{AsRawFd, OwnedFd}}; +use super::super::uapi; +use std::path::Path; +use std::fs::File; + +#[derive(Debug)] +pub struct DrmDeviceNode { + pub fd: OwnedFd, + pub path: Option, +} + +#[derive(Debug)] +pub struct Device { + pub node: DrmDeviceNode, + pub driver: uapi::DrmVersion, +} + +#[derive(Debug)] +pub struct Engine { + pub info: uapi::DrmI915EngineInfo, +} + +pub fn find_i915_device() -> Option { + uapi::find_i915_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::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::get_param(self.node.fd.as_raw_fd(), param as i32) + } +} \ No newline at end of file diff --git a/src/gpu/mod.rs b/src/gpu/mod.rs new file mode 100644 index 0000000..0b1f88f --- /dev/null +++ b/src/gpu/mod.rs @@ -0,0 +1 @@ +pub mod drm_i915; \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..9c34f18 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +pub mod native; +pub mod uapi; +pub mod gpu; \ No newline at end of file diff --git a/src/native/mod.rs b/src/native/mod.rs new file mode 100644 index 0000000..2474ec1 --- /dev/null +++ b/src/native/mod.rs @@ -0,0 +1,4 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/src/uapi/mod.rs b/src/uapi/mod.rs new file mode 100644 index 0000000..c43c414 --- /dev/null +++ b/src/uapi/mod.rs @@ -0,0 +1,209 @@ +#![allow(non_camel_case_types)] + +use std::os::fd::{AsRawFd, OwnedFd, RawFd}; +use std::ffi::{CStr, OsString, c_void}; +use libc; +use crate::gpu::drm_i915::DrmDeviceNode; + +use super::native; +use std::fs; +use std::fs::File; + +#[derive(Debug)] +pub struct DrmVersion { + pub version_major: i32, + pub version_minor: i32, + pub version_patchlevel: i32, + pub name: OsString, + pub date: OsString, + pub desc: OsString, +} + +pub fn get_drm_version(fd: RawFd) -> Option { + unsafe { + let name_vec = libc::malloc(128); + libc::memset(name_vec, 0, 128); + let date_vec = libc::malloc(128); + libc::memset(date_vec, 0, 128); + let desc_vec = libc::malloc(128); + libc::memset(desc_vec, 0, 128); + + let mut version = native::drm_version { + version_major: 0, + version_minor: 0, + version_patchlevel: 0, + name: name_vec as *mut i8, + date: date_vec as *mut i8, + desc: desc_vec as *mut i8, + name_len: 128, + date_len: 128, + desc_len: 128, + }; + let res_val = libc::ioctl(fd, native::DRM_IOCTL_VERSION, &mut version) == 0; + let res = if res_val { + let name = CStr::from_ptr(version.name).to_str().expect("Failed to convert name"); + let date = CStr::from_ptr(version.date).to_str().expect("Failed to convert date"); + let desc = CStr::from_ptr(version.desc).to_str().expect("Failed to convert desc"); + let drm_version = DrmVersion { + version_major: version.version_major, + version_minor: version.version_minor, + version_patchlevel: version.version_patchlevel, + name: OsString::from(name.to_string()), + date: OsString::from(date.to_string()), + desc: OsString::from(desc.to_string()), + }; + Some(drm_version) + } else {None}; + res + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DrmI915EngineClass { + Render, Copy, Video, VideoEnhance, Compute, Invalid +} + +#[derive(Debug)] +pub struct DrmI915EngineClassInstance { + pub engine_class: DrmI915EngineClass, + pub engine_instance: u16, +} + +pub type DrmI915EngineInfoFlags = u64; + +#[derive(Debug)] +pub struct DrmI915EngineInfo { + pub engine: DrmI915EngineClassInstance, + pub logical_instance: u16, + pub flags: DrmI915EngineInfoFlags, + pub capabilities: u64, +} + +fn engine_class_from_u16(engine_class: u16) -> DrmI915EngineClass { + match engine_class { + 0 => DrmI915EngineClass::Render, + 1 => DrmI915EngineClass::Copy, + 2 => DrmI915EngineClass::Video, + 3 => DrmI915EngineClass::VideoEnhance, + 4 => DrmI915EngineClass::Compute, + _ => DrmI915EngineClass::Invalid, + } +} + +fn engine_class_instance_from_native(engine_class_instance: native::i915_engine_class_instance) -> DrmI915EngineClassInstance { + DrmI915EngineClassInstance { + engine_class: engine_class_from_u16(engine_class_instance.engine_class), + engine_instance: engine_class_instance.engine_instance, + } +} + +fn engine_info_from_native(engine_info: native::drm_i915_engine_info) -> DrmI915EngineInfo { + DrmI915EngineInfo { + engine: engine_class_instance_from_native(engine_info.engine), + logical_instance: engine_info.logical_instance, + flags: engine_info.flags, + capabilities: engine_info.capabilities, + } +} + +impl DrmI915EngineInfo { + pub fn to_native(&self) -> native::drm_i915_engine_info { + native::drm_i915_engine_info { + engine: native::i915_engine_class_instance { + engine_class: match self.engine.engine_class { + DrmI915EngineClass::Render => 0, + DrmI915EngineClass::Copy => 1, + DrmI915EngineClass::Video => 2, + DrmI915EngineClass::VideoEnhance => 3, + DrmI915EngineClass::Compute => 4, + DrmI915EngineClass::Invalid => 0xFFFF, + }, + engine_instance: self.engine.engine_instance, + }, + logical_instance: self.logical_instance, + flags: self.flags, + capabilities: self.capabilities, + rsvd0: 0, + rsvd1: [0; 3], + rsvd2: [0; 3], + } + } + pub fn from_native(engine_info: native::drm_i915_engine_info) -> DrmI915EngineInfo { + engine_info_from_native(engine_info) + } +} + +pub fn get_engines(fd: RawFd) -> Option> { + 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::() 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 engines = engine_data.engines.as_mut_slice(engine_data.num_engines as usize); + let mut engines_res: Vec = Vec::new(); + for i in 0..engine_data.num_engines { + let engine = DrmI915EngineInfo::from_native(engines[i as usize]); + engines_res.push(engine); + } + Some(engines_res) + } +} + +pub fn get_param(fd: RawFd, param_id: i32) -> Option { + unsafe { + let mut value: i32 = 0; + let mut param = native::drm_i915_getparam { + param: param_id, + value: &mut value as *mut i32 + }; + let res = libc::ioctl(fd, native::DRM_IOCTL_I915_GETPARAM, &mut param); + if res != 0 { + return None; + } + Some(value) + } +} + +pub fn find_i915_node() -> Option { + let inodes = fs::read_dir("/dev/dri").ok()?; + for inode in inodes { + let inode = inode.ok()?; + let path = inode.path(); + let path = path.to_str()?; + if path.starts_with("/dev/dri/renderD") { + let file = File::open(path).unwrap(); + let dev = get_drm_version(file.as_raw_fd()); + if dev.is_some() && dev.unwrap().name.to_str().unwrap() == "i915" { + return Some(DrmDeviceNode { + fd: OwnedFd::from(file), + path: Some(OsString::from(path)), + }); + } + } + } + None +} + +pub fn find_i915_fd() -> Option { + return find_i915_node().map(|node| node.fd.as_raw_fd()); +} \ No newline at end of file diff --git a/tests/tests_i915_gpu.rs b/tests/tests_i915_gpu.rs new file mode 100644 index 0000000..b1fda5b --- /dev/null +++ b/tests/tests_i915_gpu.rs @@ -0,0 +1,70 @@ +use intel_gpu_uapi::*; +use std::fmt::format; +use std::os::fd::{AsRawFd, OwnedFd, RawFd}; +use std::fs::File; +use std::path::Path; + +#[test] +fn test_i915_find_device() { + let device = gpu::drm_i915::find_i915_device(); + assert!(device.is_some()); + let drm_version = device.unwrap().driver; + assert_eq!(drm_version.name.to_str().unwrap(), "i915"); + assert_eq!(drm_version.desc.to_str().unwrap(), "Intel Graphics"); +} + +#[test] +fn test_drm_version() { + let device = gpu::drm_i915::find_i915_device(); + assert!(device.is_some()); + let drm_version = device.unwrap().driver; + assert_eq!(drm_version.name.to_str().unwrap(), "i915"); + assert_eq!(drm_version.desc.to_str().unwrap(), "Intel Graphics"); + let fd_null = File::open("/dev/null").expect("Failed to open /dev/null"); + assert!(gpu::drm_i915::Device::from_fd(OwnedFd::from(fd_null)).is_none()); +} + +fn has_engine_class(engines: &Vec, engine_class: uapi::DrmI915EngineClass) -> bool { + engines.iter().filter(|engine| engine.info.engine.engine_class == engine_class).count() > 0 +} + +#[test] +fn test_i915_get_engines() { + let device = gpu::drm_i915::find_i915_device().expect("Failed to find i915 device"); + let drm_version = &device.driver; + assert_eq!(drm_version.name.to_str().unwrap(), "i915"); + assert_eq!(drm_version.desc.to_str().unwrap(), "Intel Graphics"); + let engines = device.get_engines().expect("Failed to get engines"); + assert!(engines.len() > 0); + assert!(has_engine_class(&engines, uapi::DrmI915EngineClass::Render)); + assert!(has_engine_class(&engines, uapi::DrmI915EngineClass::Copy)); + assert!(has_engine_class(&engines, uapi::DrmI915EngineClass::Video)); + assert!(has_engine_class(&engines, uapi::DrmI915EngineClass::VideoEnhance)); + // Compute engine is not always present + // assert!(has_engine_class(&engines, uapi::DrmI915EngineClass::Compute)); +} + +fn get_vendor_for_fd(fd: RawFd) -> String{ + unsafe { + let mut stat: libc::stat = std::mem::zeroed(); + libc::fstat(fd, &mut stat); + let (major, minor) = (libc::major(stat.st_rdev), + libc::minor(stat.st_rdev)); + let sysfs_path = format!("/sys/dev/char/{}:{}/device/device", major, minor); + let sysfs_path = Path::new(&sysfs_path); + let dev_id = std::fs::read_to_string(sysfs_path).expect("Unable to read device id"); + return dev_id.trim().to_string(); + } +} + +#[test] +fn test_i915_get_param() { + let device = gpu::drm_i915::find_i915_device().expect("Failed to find i915 device"); + let drm_version = &device.driver; + assert_eq!(drm_version.name.to_str().unwrap(), "i915"); + assert_eq!(drm_version.desc.to_str().unwrap(), "Intel Graphics"); + let chipset_id = device.get_param(native::I915_PARAM_CHIPSET_ID).expect("Failed to get param"); + let chip_id = format!("{:#04x}", chipset_id); + let dev_id = get_vendor_for_fd(device.node.fd.as_raw_fd()); + assert_eq!(dev_id, chip_id); +} \ No newline at end of file diff --git a/tests/tests_raw.rs b/tests/tests_raw.rs new file mode 100644 index 0000000..89ff3b1 --- /dev/null +++ b/tests/tests_raw.rs @@ -0,0 +1,66 @@ +use intel_gpu_uapi::*; +use std::ffi::c_void; +use std::ffi::CStr; +use nix::{self}; + +#[test] +fn test_drm_version_raw() { + // TODO more robust render node detection + let fd = nix::fcntl::open("/dev/dri/renderD129", nix::fcntl::OFlag::O_RDWR | nix::fcntl::OFlag::O_CLOEXEC, nix::sys::stat::Mode::empty()) + .expect("Failed to open /dev/dri/renderD129"); + unsafe { + let name_vec = libc::malloc(128); + let date_vec = libc::malloc(128); + let desc_vec = libc::malloc(128); + + let mut version = native::drm_version { + version_major: 0, + version_minor: 0, + version_patchlevel: 0, + name: name_vec as *mut i8, + date: date_vec as *mut i8, + desc: desc_vec as *mut i8, + name_len: 128, + date_len: 128, + desc_len: 128, + }; + assert!(libc::ioctl(fd, native::DRM_IOCTL_VERSION, &mut version) == 0); + println!("version_major: {}, version_minor: {}, version_patchlevel: {}, name: {:?}, date: {:?}, desc: {:?}", + version.version_major, + version.version_minor, + version.version_patchlevel, + CStr::from_ptr(version.name), + CStr::from_ptr(version.date), + CStr::from_ptr(version.desc)); + } +} + +#[test] +fn test_i915_query_raw() { + let fd = nix::fcntl::open("/dev/dri/renderD129", nix::fcntl::OFlag::O_RDWR | nix::fcntl::OFlag::O_CLOEXEC, nix::sys::stat::Mode::empty()) + .expect("Failed to open /dev/dri/renderD129"); + 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::() 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, + }; + assert!(libc::ioctl(fd, native::DRM_IOCTL_I915_QUERY, &mut query) == 0); + let engine_info = libc::malloc(query_item.length as usize) + as *mut native::drm_i915_query_engine_info; + query_item.data_ptr = engine_info as u64; + assert!(libc::ioctl(fd, native::DRM_IOCTL_I915_QUERY, &mut query) == 0); + println!("engine_info: {:?}", *engine_info); + let engine_data = engine_info.as_mut().unwrap(); + let engines = engine_data.engines.as_mut_slice(engine_data.num_engines as usize); + for engine in engines { + println!("engine: {:?}", engine); + } + } +} diff --git a/tests/tests_uapi.rs b/tests/tests_uapi.rs new file mode 100644 index 0000000..ea5df52 --- /dev/null +++ b/tests/tests_uapi.rs @@ -0,0 +1,20 @@ +#![allow(unused_imports)] + +use intel_gpu_uapi::*; +use uapi::find_i915_node; +use std::fs; +use std::{fs::File, os::fd::AsRawFd}; + +#[test] +fn test_drm_version() { + let node = find_i915_node().expect("Failed to find i915 fd"); + let drm_version = uapi::get_drm_version(node.fd.as_raw_fd()).expect("Failed to get drm version"); + println!("{:?}", drm_version); +} + +#[test] +fn test_i915_get_engines() { + let node = find_i915_node().expect("Failed to find i915 fd"); + let engines = uapi::get_engines(node.fd.as_raw_fd()).expect("Failed to get engines"); + println!("{:?}", engines); +} \ No newline at end of file