diff --git a/src/gpu/i915/mod.rs b/src/gpu/i915/mod.rs index 02d98d9..5d0eb90 100644 --- a/src/gpu/i915/mod.rs +++ b/src/gpu/i915/mod.rs @@ -1,7 +1,6 @@ use std::{ffi::OsString, os::fd::{AsRawFd, OwnedFd}}; -use crate::uapi::i915::DrmGemHandle; - -use super::super::uapi; +use crate::{native, uapi::{self, i915::DrmGemTileInfo}}; +use uapi::i915::DrmGemHandle; use std::path::Path; use std::fs::File; @@ -19,6 +18,42 @@ pub struct GemHandle<'a> { pub node: &'a DrmDeviceNode, } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u32)] +pub enum DrmCacheType { + None = native::I915_CACHING_NONE, + Cached = native::I915_CACHING_CACHED, + Display = native::I915_CACHING_DISPLAY, +} + +impl From for DrmCacheType { + fn from(val: u32) -> DrmCacheType { + match val { + native::I915_CACHING_NONE => DrmCacheType::None, + native::I915_CACHING_CACHED => DrmCacheType::Cached, + native::I915_CACHING_DISPLAY => DrmCacheType::Display, + _ => panic!("Invalid cache type encountered"), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct GemTileInfo { + pub tiling_mode: u32, + pub swizzle_mode: u32, + pub phys_swizzle_mode: u32, +} + +impl From for GemTileInfo { + fn from(info: DrmGemTileInfo) -> GemTileInfo { + GemTileInfo { + tiling_mode: info.tiling_mode, + swizzle_mode: info.swizzle_mode, + phys_swizzle_mode: info.phys_swizzle_mode, + } + } +} + /// An owned GEM handle that will be closed when dropped impl GemHandle<'_> { pub fn new(node: &DrmDeviceNode, size: u64) -> Option { @@ -47,6 +82,14 @@ impl GemHandle<'_> { return unsafe { uapi::i915::close_gem_ref(self.node.fd.as_raw_fd(), &self.handle) }; } + pub fn get_tiling(&self) -> Result { + uapi::i915::gem_get_tiling(self.node.fd.as_raw_fd(), &self.handle).map(|info| GemTileInfo::from(info)) + } + + pub fn get_caching(&self) -> Result { + uapi::i915::gem_get_caching(self.node.fd.as_raw_fd(), &self.handle).map(|info| DrmCacheType::try_from(info).unwrap()) + } + pub fn has_tiling(&self) -> Result { uapi::i915::gem_has_tiling(self.node.fd.as_raw_fd(), &self.handle) } diff --git a/src/uapi/i915/mod.rs b/src/uapi/i915/mod.rs index 22d622f..c07a3a4 100644 --- a/src/uapi/i915/mod.rs +++ b/src/uapi/i915/mod.rs @@ -204,10 +204,19 @@ pub fn close_gem(fd: RawFd, handle: DrmGemHandle) -> Result<(), i32> { pub enum GemIoctlError { InvalidHandle, PermissionDenied, + UnsupportedOnDevice, + UnsupportedOnHandle, Unknown(i32), } -pub fn gem_has_tiling(fd: RawFd, handle: &DrmGemHandle) -> Result { +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct DrmGemTileInfo { + pub tiling_mode: u32, + pub swizzle_mode: u32, + pub phys_swizzle_mode: u32, +} + +pub fn gem_get_tiling(fd: RawFd, handle: &DrmGemHandle) -> Result { unsafe { let mut tiling = native::drm_i915_gem_get_tiling { handle: handle.handle, @@ -216,12 +225,47 @@ pub fn gem_has_tiling(fd: RawFd, handle: &DrmGemHandle) -> Result Ok(tile_info), + libc::ENOENT => Err(GemIoctlError::InvalidHandle), + libc::EPERM => Err(GemIoctlError::PermissionDenied), + libc::EOPNOTSUPP => Err(GemIoctlError::UnsupportedOnDevice), + _ => Err(GemIoctlError::Unknown(res)), + } + } +} + +pub fn gem_has_tiling(fd: RawFd, handle: &DrmGemHandle) -> Result { + let res = gem_get_tiling(fd, handle); + if res.is_ok() { + return Ok(true); + } + if res.is_err() && res.unwrap_err() == GemIoctlError::UnsupportedOnDevice { + return Ok(false); + } + return Err(res.unwrap_err()); +} + +pub fn gem_get_caching(fd: RawFd, handle: &DrmGemHandle) -> Result { + unsafe { + let mut caching = native::drm_i915_gem_caching { + handle: handle.handle, + caching: 0, + }; + let res = libc::ioctl(fd, native::DRM_IOCTL_I915_GEM_GET_CACHING, &mut caching); let errno = *libc::__errno_location(); match errno { - 0 => Ok(true), + 0 => Ok(caching.caching), libc::ENOENT => Err(GemIoctlError::InvalidHandle), libc::EPERM => Err(GemIoctlError::PermissionDenied), - libc::EINVAL => Ok(false), + libc::ENODEV => Err(GemIoctlError::UnsupportedOnDevice), + libc::EOPNOTSUPP => Err(GemIoctlError::UnsupportedOnHandle), _ => Err(GemIoctlError::Unknown(res)), } } @@ -237,7 +281,6 @@ pub fn gem_is_valid(fd: RawFd, handle: &DrmGemHandle) -> Result