diff --git a/rutabaga_gfx/src/rutabaga_gralloc/minigbm.rs b/rutabaga_gfx/src/rutabaga_gralloc/minigbm.rs index 812f32a27c..2ba7a5a932 100644 --- a/rutabaga_gfx/src/rutabaga_gralloc/minigbm.rs +++ b/rutabaga_gfx/src/rutabaga_gralloc/minigbm.rs @@ -13,6 +13,7 @@ use std::fs::File; use std::io::Error; use std::io::Seek; use std::io::SeekFrom; +use std::os::fd::FromRawFd; use std::os::raw::c_char; use std::sync::Arc; @@ -21,8 +22,6 @@ use crate::rutabaga_gralloc::gralloc::Gralloc; use crate::rutabaga_gralloc::gralloc::ImageAllocationInfo; use crate::rutabaga_gralloc::gralloc::ImageMemoryRequirements; use crate::rutabaga_gralloc::minigbm_bindings::*; -use crate::rutabaga_gralloc::rendernode; -use crate::rutabaga_os::AsRawDescriptor; use crate::rutabaga_os::FromRawDescriptor; use crate::rutabaga_utils::*; @@ -60,29 +59,37 @@ impl MinigbmDevice { /// Returns a new `MinigbmDevice` if there is a rendernode in `/dev/dri/` that is accepted by /// the minigbm library. pub fn init() -> RutabagaResult> { - let undesired: &[&str] = &["vgem", "pvr"]; - let fd = rendernode::open_device(undesired)?; - + let descriptor: File; + let device_name: &str; + let gbm: *mut gbm_device; // SAFETY: - // gbm_create_device is safe to call with a valid fd, and we check that a valid one is - // returned. If the fd does not refer to a DRM device, gbm_create_device will reject it. - let gbm = unsafe { gbm_create_device(fd.as_raw_descriptor()) }; - if gbm.is_null() { - return Err(RutabagaError::IoError(Error::last_os_error())); + // Safe because minigbm_create_default_device is safe to call with an unused fd, + // and fd is guaranteed to be overwritten with a valid descriptor when a non-null + // pointer is returned. + unsafe { + let mut fd = -1; + + gbm = minigbm_create_default_device(&mut fd); + if gbm.is_null() { + return Err(RutabagaError::IoError(Error::last_os_error())); + } + descriptor = File::from_raw_fd(fd); } // SAFETY: - // Safe because a valid minigbm device has a statically allocated string associated with - // it, which is valid for the lifetime of the process. - let backend_name: *const c_char = unsafe { gbm_device_get_backend_name(gbm) }; - // SAFETY: - // Safe because a valid minigbm device has a statically allocated string associated with - // it, which is valid for the lifetime of the process. - let c_str: &CStr = unsafe { CStr::from_ptr(backend_name) }; - let device_name: &str = c_str.to_str()?; + // Safe because the string returned by gbm_device_get_backend_name() exists at least + // as long as the associated gbm_device. + unsafe { + let backend_name: *const c_char = gbm_device_get_backend_name(gbm); + let c_str: &CStr = CStr::from_ptr(backend_name); + device_name = c_str.to_str()?; + } Ok(Box::new(MinigbmDevice { - minigbm_device: Arc::new(MinigbmDeviceInner { _fd: fd, gbm }), + minigbm_device: Arc::new(MinigbmDeviceInner { + _fd: descriptor, + gbm, + }), last_buffer: None, device_name, })) diff --git a/rutabaga_gfx/src/rutabaga_gralloc/minigbm_bindings.rs b/rutabaga_gfx/src/rutabaga_gralloc/minigbm_bindings.rs index 8ed4221141..f8ae7fda18 100644 --- a/rutabaga_gfx/src/rutabaga_gralloc/minigbm_bindings.rs +++ b/rutabaga_gfx/src/rutabaga_gralloc/minigbm_bindings.rs @@ -272,3 +272,6 @@ extern "C" { plane: c_int, ) -> *mut c_void; } +extern "C" { + pub fn minigbm_create_default_device(out_fd: *mut c_int) -> *mut gbm_device; +} diff --git a/rutabaga_gfx/src/rutabaga_gralloc/mod.rs b/rutabaga_gfx/src/rutabaga_gralloc/mod.rs index c4ceb2e5c5..a4ea8e57af 100644 --- a/rutabaga_gfx/src/rutabaga_gralloc/mod.rs +++ b/rutabaga_gfx/src/rutabaga_gralloc/mod.rs @@ -12,7 +12,6 @@ mod formats; mod gralloc; mod minigbm; mod minigbm_bindings; -mod rendernode; mod system_gralloc; mod vulkano_gralloc; diff --git a/rutabaga_gfx/src/rutabaga_gralloc/rendernode.rs b/rutabaga_gfx/src/rutabaga_gralloc/rendernode.rs deleted file mode 100644 index 4ff5f4e880..0000000000 --- a/rutabaga_gfx/src/rutabaga_gralloc/rendernode.rs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2018 The ChromiumOS Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#![cfg(feature = "minigbm")] - -use std::ffi::CString; -use std::fs::File; -use std::fs::OpenOptions; -use std::os::raw::c_char; -use std::os::raw::c_int; -use std::os::raw::c_uint; -#[cfg(target_pointer_width = "64")] -use std::os::raw::c_ulong; -use std::os::unix::io::AsRawFd; -use std::path::Path; -use std::ptr::null_mut; - -use nix::ioctl_readwrite; - -use crate::rutabaga_utils::RutabagaError; -use crate::rutabaga_utils::RutabagaResult; - -// Consistent with __kernel_size_t in include/uapi/asm-generic/posix_types.h. -#[cfg(not(target_pointer_width = "64"))] -#[allow(non_camel_case_types)] -type __kernel_size_t = c_uint; -#[cfg(target_pointer_width = "64")] -#[allow(non_camel_case_types)] -type __kernel_size_t = c_ulong; - -const DRM_IOCTL_BASE: c_uint = 0x64; -const DRM_IOCTL_VERSION: c_uint = 0x00; - -#[repr(C)] -#[derive(Copy, Clone)] -pub struct drm_version { - version_major: c_int, - version_minor: c_int, - version_patchlevel: c_int, - name_len: __kernel_size_t, - name: *mut c_char, - date_len: __kernel_size_t, - date: *mut c_char, - desc_len: __kernel_size_t, - desc: *mut c_char, -} - -ioctl_readwrite!( - drm_get_version, - DRM_IOCTL_BASE, - DRM_IOCTL_VERSION, - drm_version -); - -fn get_drm_device_name(fd: &File) -> RutabagaResult { - let mut version = drm_version { - version_major: 0, - version_minor: 0, - version_patchlevel: 0, - name_len: 0, - name: null_mut(), - date_len: 0, - date: null_mut(), - desc_len: 0, - desc: null_mut(), - }; - - // TODO(b/315870313): Add safety comment - #[allow(clippy::undocumented_unsafe_blocks)] - // Get the length of the device name. - unsafe { - drm_get_version(fd.as_raw_fd(), &mut version)?; - } - - // Enough bytes to hold the device name and terminating null character. - let mut name_bytes: Vec = vec![0; (version.name_len + 1) as usize]; - let mut version = drm_version { - version_major: 0, - version_minor: 0, - version_patchlevel: 0, - name_len: name_bytes.len() as __kernel_size_t, - name: name_bytes.as_mut_ptr() as *mut c_char, - date_len: 0, - date: null_mut(), - desc_len: 0, - desc: null_mut(), - }; - - // SAFETY: - // Safe as no more than name_len + 1 bytes will be written to name. - unsafe { - drm_get_version(fd.as_raw_fd(), &mut version)?; - } - - CString::new(&name_bytes[..(version.name_len as usize)])? - .into_string() - .map_err(|_| RutabagaError::SpecViolation("couldn't convert string")) -} - -/// Returns a `fd` for an opened rendernode device, while filtering out specified -/// undesired drivers. -pub fn open_device(undesired: &[&str]) -> RutabagaResult { - const DRM_DIR_NAME: &str = "/dev/dri"; - const DRM_MAX_MINOR: u32 = 15; - const RENDER_NODE_START: u32 = 128; - - for n in RENDER_NODE_START..=RENDER_NODE_START + DRM_MAX_MINOR { - let path = Path::new(DRM_DIR_NAME).join(format!("renderD{}", n)); - - if let Ok(fd) = OpenOptions::new().read(true).write(true).open(path) { - if let Ok(name) = get_drm_device_name(&fd) { - if !undesired.iter().any(|item| *item == name) { - return Ok(fd); - } - } - } - } - - Err(RutabagaError::SpecViolation("no DRM rendernode opened")) -}