1
0
Fork 0
forked from wry/wry

video: prefer non-nvidia devices when selecting render device

This commit is contained in:
Julian Orth 2022-11-13 15:18:50 +01:00
parent 141997d9d6
commit 79ee6900fa
6 changed files with 107 additions and 11 deletions

View file

@ -4,7 +4,7 @@ use {
fixed::Fixed,
ifs::wl_seat::wl_pointer::{CONTINUOUS, FINGER, HORIZONTAL_SCROLL, VERTICAL_SCROLL, WHEEL},
render::Framebuffer,
video::drm::ConnectorType,
video::drm::{ConnectorType, DrmError, DrmVersion},
},
std::{
any::Any,
@ -222,4 +222,5 @@ pub trait BackendDrmDevice {
fn on_change(&self, cb: Rc<dyn Fn()>);
fn dev_t(&self) -> c::dev_t;
fn make_render_device(self: Rc<Self>);
fn version(&self) -> Result<DrmVersion, DrmError>;
}

View file

@ -21,9 +21,9 @@ use {
drm::{
drm_mode_modeinfo, Change, ConnectorStatus, ConnectorType, DrmBlob, DrmConnector,
DrmCrtc, DrmEncoder, DrmError, DrmEvent, DrmFramebuffer, DrmMaster, DrmModeInfo,
DrmObject, DrmPlane, DrmProperty, DrmPropertyDefinition, DrmPropertyType, PropBlob,
DRM_CLIENT_CAP_ATOMIC, DRM_MODE_ATOMIC_ALLOW_MODESET, DRM_MODE_ATOMIC_NONBLOCK,
DRM_MODE_PAGE_FLIP_EVENT,
DrmObject, DrmPlane, DrmProperty, DrmPropertyDefinition, DrmPropertyType,
DrmVersion, PropBlob, DRM_CLIENT_CAP_ATOMIC, DRM_MODE_ATOMIC_ALLOW_MODESET,
DRM_MODE_ATOMIC_NONBLOCK, DRM_MODE_PAGE_FLIP_EVENT,
},
gbm::{GbmDevice, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING, GBM_BO_USE_SCANOUT},
ModifiedFormat, INVALID_MODIFIER,
@ -93,6 +93,10 @@ impl BackendDrmDevice for MetalDrmDevice {
fn make_render_device(self: Rc<Self>) {
self.backend.make_render_device(&self, true);
}
fn version(&self) -> Result<DrmVersion, DrmError> {
self.gbm.drm.version()
}
}
pub struct HandleEvents {

View file

@ -17,7 +17,7 @@ use {
queue::AsyncQueue, syncqueue::SyncQueue,
},
video::{
drm::{ConnectorType, Drm, DrmError},
drm::{ConnectorType, Drm, DrmError, DrmVersion},
gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING},
ModifiedFormat, INVALID_MODIFIER,
},
@ -291,7 +291,7 @@ impl XBackend {
self.state
.backend_events
.push(BackendEvent::NewDrmDevice(Rc::new(XDrmDevice {
_backend: self.clone(),
backend: self.clone(),
id: self.drm_device_id,
dev: self.drm_dev,
})));
@ -939,7 +939,7 @@ impl XBackend {
}
struct XDrmDevice {
_backend: Rc<XBackend>,
backend: Rc<XBackend>,
id: DrmDeviceId,
dev: dev_t,
}
@ -965,6 +965,10 @@ impl BackendDrmDevice for XDrmDevice {
log::warn!("make_render_device is not supported by the X backend");
// nothing
}
fn version(&self) -> Result<DrmVersion, DrmError> {
self.backend.gbm.drm.version()
}
}
struct XOutput {

View file

@ -49,6 +49,7 @@ use {
xwayland::{self, XWaylandEvent},
},
ahash::AHashMap,
bstr::ByteSlice,
jay_config::PciId,
std::{
cell::{Cell, RefCell},
@ -284,8 +285,21 @@ impl State {
config.devices_enumerated()
}
if self.render_ctx.get().is_none() {
if let Some(dev) = self.drm_devs.lock().values().next() {
for dev in self.drm_devs.lock().values() {
if let Ok(version) = dev.dev.version() {
if version.name.contains_str("nvidia") {
continue;
}
}
dev.make_render_device();
if self.render_ctx.get().is_some() {
break;
}
}
if self.render_ctx.get().is_none() {
if let Some(dev) = self.drm_devs.lock().values().next() {
dev.make_render_device();
}
}
}
}

View file

@ -34,7 +34,7 @@ use crate::{
utils::{errorfmt::ErrorFmt, stack::Stack, syncqueue::SyncQueue, vec_ext::VecExt},
video::{
dmabuf::DmaBuf,
drm::sys::{DRM_CAP_CURSOR_HEIGHT, DRM_CAP_CURSOR_WIDTH},
drm::sys::{get_version, DRM_CAP_CURSOR_HEIGHT, DRM_CAP_CURSOR_WIDTH},
INVALID_MODIFIER,
},
};
@ -103,6 +103,8 @@ pub enum DrmError {
ReadEvents(#[source] OsError),
#[error("Read invalid data from drm device")]
InvalidRead,
#[error("Could not determine the drm version")]
Version(#[source] OsError),
}
fn render_node_name(fd: c::c_int) -> Result<Ustring, DrmError> {
@ -165,6 +167,10 @@ impl Drm {
pub fn get_nodes(&self) -> Result<AHashMap<NodeType, CString>, DrmError> {
get_nodes(self.fd.raw()).map_err(DrmError::GetNodes)
}
pub fn version(&self) -> Result<DrmVersion, DrmError> {
get_version(self.fd.raw()).map_err(DrmError::Version)
}
}
pub struct DrmMaster {
@ -590,6 +596,16 @@ pub struct DrmModeInfo {
pub name: BString,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct DrmVersion {
pub version_major: i32,
pub version_minor: i32,
pub version_patchlevel: i32,
pub name: BString,
pub date: BString,
pub desc: BString,
}
impl DrmModeInfo {
pub fn create_blob(&self, master: &Rc<DrmMaster>) -> Result<PropBlob, DrmError> {
let raw = self.to_raw();

View file

@ -8,7 +8,7 @@ use {
DrmBlob, DrmCardResources, DrmConnector, DrmConnectorInfo, DrmCrtc, DrmEncoder,
DrmEncoderInfo, DrmError, DrmFb, DrmModeInfo, DrmPlane, DrmPlaneInfo, DrmProperty,
DrmPropertyDefinition, DrmPropertyEnumValue, DrmPropertyType, DrmPropertyValue,
NodeType,
DrmVersion, NodeType,
},
},
ahash::AHashMap,
@ -18,7 +18,7 @@ use {
io::{BufRead, BufReader},
mem,
},
uapi::{c, OwnedFd, Pod, Ustring},
uapi::{c, pod_zeroed, OwnedFd, Pod, Ustring},
};
pub unsafe fn ioctl<T>(fd: c::c_int, request: c::c_ulong, t: &mut T) -> Result<c::c_int, OsError> {
@ -1075,3 +1075,60 @@ pub fn mode_getprobblob<T: Pod + ?Sized>(
}
Ok(res.length as _)
}
#[repr(C)]
struct drm_version {
version_major: c::c_int,
version_minor: c::c_int,
version_patchlevel: c::c_int,
name_len: usize, // actually __kernel_size_t but nobody cares about x32
name: *mut u8,
date_len: usize,
date: *mut u8,
desc_len: usize,
desc: *mut u8,
}
unsafe impl Pod for drm_version {}
const DRM_IOCTL_VERSION: u64 = drm_iowr::<drm_version>(0x00);
pub fn get_version(fd: c::c_int) -> Result<DrmVersion, OsError> {
let mut name = Vec::<u8>::new();
let mut date = Vec::<u8>::new();
let mut desc = Vec::<u8>::new();
let mut res: drm_version = pod_zeroed();
loop {
res.name_len = name.capacity();
res.name = name.as_mut_ptr();
res.date_len = date.capacity();
res.date = date.as_mut_ptr();
res.desc_len = desc.capacity();
res.desc = desc.as_mut_ptr();
unsafe {
ioctl(fd, DRM_IOCTL_VERSION, &mut res)?;
}
if res.name_len <= name.capacity()
&& res.date_len <= date.capacity()
&& res.desc_len <= desc.capacity()
{
break;
}
name.reserve_exact(res.name_len);
date.reserve_exact(res.date_len);
desc.reserve_exact(res.desc_len);
}
unsafe {
name.set_len(res.name_len);
date.set_len(res.date_len);
desc.set_len(res.desc_len);
}
Ok(DrmVersion {
version_major: res.version_major,
version_minor: res.version_minor,
version_patchlevel: res.version_patchlevel,
name: name.into(),
date: date.into(),
desc: desc.into(),
})
}