1
0
Fork 0
forked from wry/wry

video: add udmabuf allocator

This commit is contained in:
Julian Orth 2024-09-01 20:23:04 +02:00
parent 2579834a60
commit 62cd29056a
33 changed files with 883 additions and 256 deletions

View file

@ -1,5 +1,6 @@
use {
crate::{
allocator::Allocator,
async_engine::SpawnedFuture,
backend::{
AxisSource, Backend, BackendEvent, Connector, ConnectorEvent, ConnectorId,
@ -15,14 +16,18 @@ use {
test_error::TestResult, test_gfx_api::TestGfxCtx, test_utils::test_expected_event::TEEH,
},
state::State,
udmabuf::Udmabuf,
utils::{
clonecell::CloneCell, copyhashmap::CopyHashMap, on_change::OnChange, oserror::OsError,
syncqueue::SyncQueue,
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
on_change::OnChange, oserror::OsError, syncqueue::SyncQueue,
},
video::{
drm::{ConnectorType, Drm},
gbm::{GbmDevice, GbmError},
},
video::drm::{ConnectorType, Drm},
},
bstr::ByteSlice,
std::{any::Any, cell::Cell, io, os::unix::ffi::OsStrExt, pin::Pin, rc::Rc},
std::{any::Any, cell::Cell, error::Error, io, os::unix::ffi::OsStrExt, pin::Pin, rc::Rc},
thiserror::Error,
uapi::c,
};
@ -37,6 +42,10 @@ pub enum TestBackendError {
OpenDrmNode(String, #[source] OsError),
#[error("Could not create a render context")]
RenderContext(#[source] GfxError),
#[error("Could not create a gbm device")]
CreateGbmDevice(#[source] GbmError),
#[error("Could not create any allocator")]
CreateAllocator,
}
pub struct TestBackend {
@ -124,17 +133,21 @@ impl TestBackend {
}
}
pub fn install_render_context(&self) -> TestResult {
pub fn install_render_context(&self, prefer_udmabuf: bool) -> TestResult {
if self.render_context_installed.get() {
return Ok(());
}
self.create_render_context()?;
self.create_render_context(prefer_udmabuf)?;
self.render_context_installed.set(true);
Ok(())
}
pub fn install_default(&self) -> TestResult {
self.install_render_context()?;
self.install_default2(true)
}
pub fn install_default2(&self, prefer_udmabuf: bool) -> TestResult {
self.install_render_context(prefer_udmabuf)?;
self.state
.backend_events
.push(BackendEvent::NewConnector(self.default_connector.clone()));
@ -150,47 +163,35 @@ impl TestBackend {
Ok(())
}
fn create_render_context(&self) -> Result<(), TestBackendError> {
let dri = match std::fs::read_dir("/dev/dri") {
Ok(d) => d,
Err(e) => return Err(TestBackendError::ReadDri(e)),
};
let mut files = vec![];
for f in dri {
let f = match f {
Ok(f) => f,
Err(e) => return Err(TestBackendError::ReadDri(e)),
fn create_render_context(&self, prefer_udmabuf: bool) -> Result<(), TestBackendError> {
macro_rules! constructor {
($c:expr) => {
(&|| {
$c.map(|a| Rc::new(a) as Rc<dyn Allocator>)
.map_err(|e| Box::new(e) as Box<dyn Error>)
}) as &dyn Fn() -> Result<Rc<dyn Allocator>, Box<dyn Error>>
};
files.push(f.path());
}
let node = 'node: {
for f in &files {
if let Some(file) = f.file_name() {
if file.as_bytes().starts_with_str("renderD") {
break 'node f;
}
let udmabuf = ("udmabuf", constructor!(Udmabuf::new()));
let gbm = ("GBM", constructor!(create_gbm_allocator()));
let allocators = match prefer_udmabuf {
true => [udmabuf, gbm],
false => [gbm, udmabuf],
};
let mut allocator = None::<Rc<dyn Allocator>>;
for (name, f) in allocators {
match f() {
Ok(a) => {
allocator = Some(a);
break;
}
Err(e) => {
log::error!("Could not create {name} allocator: {}", ErrorFmt(&*e));
}
}
for f in &files {
if let Some(file) = f.file_name() {
if file.as_bytes().starts_with_str("card") {
break 'node f;
}
}
}
return Err(TestBackendError::NoDrmNode);
};
let file = match uapi::open(node.as_path(), c::O_RDWR | c::O_CLOEXEC, 0) {
Ok(f) => Rc::new(f),
Err(e) => {
return Err(TestBackendError::OpenDrmNode(
node.as_os_str().as_bytes().as_bstr().to_string(),
e.into(),
))
}
};
let drm = Drm::open_existing(file);
let ctx = match TestGfxCtx::new(&drm) {
}
let allocator = allocator.ok_or(TestBackendError::CreateAllocator)?;
let ctx = match TestGfxCtx::new(allocator) {
Ok(ctx) => ctx,
Err(e) => return Err(TestBackendError::RenderContext(e)),
};
@ -199,6 +200,50 @@ impl TestBackend {
}
}
fn create_gbm_allocator() -> Result<GbmDevice, TestBackendError> {
let dri = match std::fs::read_dir("/dev/dri") {
Ok(d) => d,
Err(e) => return Err(TestBackendError::ReadDri(e)),
};
let mut files = vec![];
for f in dri {
let f = match f {
Ok(f) => f,
Err(e) => return Err(TestBackendError::ReadDri(e)),
};
files.push(f.path());
}
let node = 'node: {
for f in &files {
if let Some(file) = f.file_name() {
if file.as_bytes().starts_with_str("renderD") {
break 'node f;
}
}
}
for f in &files {
if let Some(file) = f.file_name() {
if file.as_bytes().starts_with_str("card") {
break 'node f;
}
}
}
return Err(TestBackendError::NoDrmNode);
};
let file = match uapi::open(node.as_path(), c::O_RDWR | c::O_CLOEXEC, 0) {
Ok(f) => Rc::new(f),
Err(e) => {
return Err(TestBackendError::OpenDrmNode(
node.as_os_str().as_bytes().as_bstr().to_string(),
e.into(),
))
}
};
let drm = Drm::open_existing(file);
let gbm = GbmDevice::new(&drm).map_err(TestBackendError::CreateGbmDevice)?;
Ok(gbm)
}
impl Backend for TestBackend {
fn run(self: Rc<Self>) -> SpawnedFuture<Result<(), Box<dyn std::error::Error>>> {
let future = (self.test_future)(&self.state);