drm_feedback: move table generation into workspace crate
This commit is contained in:
parent
6d569bd4b7
commit
81a718aa74
5 changed files with 185 additions and 116 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
|
@ -731,6 +731,7 @@ dependencies = [
|
||||||
"jay-cpu-worker",
|
"jay-cpu-worker",
|
||||||
"jay-criteria",
|
"jay-criteria",
|
||||||
"jay-dbus-core",
|
"jay-dbus-core",
|
||||||
|
"jay-drm-feedback",
|
||||||
"jay-edid",
|
"jay-edid",
|
||||||
"jay-eventfd-cache",
|
"jay-eventfd-cache",
|
||||||
"jay-formats",
|
"jay-formats",
|
||||||
|
|
@ -840,6 +841,17 @@ dependencies = [
|
||||||
"uapi",
|
"uapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jay-drm-feedback"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"byteorder",
|
||||||
|
"jay-video-types",
|
||||||
|
"thiserror",
|
||||||
|
"uapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jay-edid"
|
name = "jay-edid"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ members = [
|
||||||
"clientmem",
|
"clientmem",
|
||||||
"allocator",
|
"allocator",
|
||||||
"output-schedule",
|
"output-schedule",
|
||||||
|
"drm-feedback",
|
||||||
"pango",
|
"pango",
|
||||||
"libinput",
|
"libinput",
|
||||||
"toml-config",
|
"toml-config",
|
||||||
|
|
@ -99,6 +100,7 @@ jay-theme = { version = "0.1.0", path = "theme" }
|
||||||
jay-clientmem = { version = "0.1.0", path = "clientmem" }
|
jay-clientmem = { version = "0.1.0", path = "clientmem" }
|
||||||
jay-allocator = { version = "0.1.0", path = "allocator" }
|
jay-allocator = { version = "0.1.0", path = "allocator" }
|
||||||
jay-output-schedule = { version = "0.1.0", path = "output-schedule" }
|
jay-output-schedule = { version = "0.1.0", path = "output-schedule" }
|
||||||
|
jay-drm-feedback = { version = "0.1.0", path = "drm-feedback" }
|
||||||
jay-pango = { version = "0.1.0", path = "pango" }
|
jay-pango = { version = "0.1.0", path = "pango" }
|
||||||
jay-libinput = { version = "0.1.0", path = "libinput" }
|
jay-libinput = { version = "0.1.0", path = "libinput" }
|
||||||
|
|
||||||
|
|
|
||||||
13
drm-feedback/Cargo.toml
Normal file
13
drm-feedback/Cargo.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "jay-drm-feedback"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
license = "GPL-3.0-only"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
jay-video-types = { version = "0.1.0", path = "../video-types" }
|
||||||
|
|
||||||
|
ahash = "0.8.7"
|
||||||
|
byteorder = "1.5.0"
|
||||||
|
thiserror = "2.0.11"
|
||||||
|
uapi = "0.2.13"
|
||||||
149
drm-feedback/src/lib.rs
Normal file
149
drm-feedback/src/lib.rs
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
use {
|
||||||
|
ahash::AHashMap,
|
||||||
|
byteorder::{NativeEndian, WriteBytesExt},
|
||||||
|
jay_video_types::Modifier,
|
||||||
|
std::{io::Write, rc::Rc},
|
||||||
|
thiserror::Error,
|
||||||
|
uapi::{OwnedFd, c},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DrmFeedbackIds {
|
||||||
|
next: std::cell::Cell<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DrmFeedbackIds {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
next: std::cell::Cell::new(1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DrmFeedbackIds {
|
||||||
|
pub fn next(&self) -> DrmFeedbackId {
|
||||||
|
let id = self.next.get();
|
||||||
|
self.next.set(id + 1);
|
||||||
|
DrmFeedbackId(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub struct DrmFeedbackId(u64);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DrmFeedbackShared {
|
||||||
|
pub fd: Rc<OwnedFd>,
|
||||||
|
pub size: usize,
|
||||||
|
pub main_device: c::dev_t,
|
||||||
|
pub indices: AHashMap<(u32, Modifier), u16>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DrmFeedback {
|
||||||
|
pub id: DrmFeedbackId,
|
||||||
|
pub shared: Rc<DrmFeedbackShared>,
|
||||||
|
pub tranches: Vec<DrmFeedbackTranche>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct DrmFeedbackTranche {
|
||||||
|
pub device: c::dev_t,
|
||||||
|
pub indices: Vec<u16>,
|
||||||
|
pub scanout: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DrmFeedback {
|
||||||
|
pub fn new<C: DrmFeedbackContext + ?Sized>(
|
||||||
|
ids: &DrmFeedbackIds,
|
||||||
|
render_ctx: &C,
|
||||||
|
) -> Result<Self, DrmFeedbackError> {
|
||||||
|
let main_device = match render_ctx.main_device() {
|
||||||
|
Some(dev) => dev,
|
||||||
|
_ => return Err(DrmFeedbackError::NoDrmDevice),
|
||||||
|
};
|
||||||
|
let (data, index_map) = create_fd_data(render_ctx);
|
||||||
|
let mut memfd =
|
||||||
|
uapi::memfd_create("drm_feedback", c::MFD_CLOEXEC | c::MFD_ALLOW_SEALING).unwrap();
|
||||||
|
memfd.write_all(&data).unwrap();
|
||||||
|
uapi::lseek(memfd.raw(), 0, c::SEEK_SET).unwrap();
|
||||||
|
uapi::fcntl_add_seals(
|
||||||
|
memfd.raw(),
|
||||||
|
c::F_SEAL_SEAL | c::F_SEAL_GROW | c::F_SEAL_SHRINK | c::F_SEAL_WRITE,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
Ok(Self {
|
||||||
|
id: ids.next(),
|
||||||
|
tranches: vec![DrmFeedbackTranche {
|
||||||
|
device: main_device,
|
||||||
|
indices: (0..index_map.len()).map(|v| v as u16).collect(),
|
||||||
|
scanout: false,
|
||||||
|
}],
|
||||||
|
shared: Rc::new(DrmFeedbackShared {
|
||||||
|
fd: Rc::new(memfd),
|
||||||
|
size: data.len(),
|
||||||
|
main_device,
|
||||||
|
indices: index_map,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn for_scanout(
|
||||||
|
&self,
|
||||||
|
ids: &DrmFeedbackIds,
|
||||||
|
devnum: c::dev_t,
|
||||||
|
formats: &[(u32, Modifier)],
|
||||||
|
) -> Result<Option<Self>, DrmFeedbackError> {
|
||||||
|
let mut tranches = vec![];
|
||||||
|
{
|
||||||
|
let mut indices = vec![];
|
||||||
|
for (format, modifier) in formats {
|
||||||
|
if let Some(idx) = self.shared.indices.get(&(*format, *modifier)) {
|
||||||
|
indices.push(*idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if indices.len() > 0 {
|
||||||
|
tranches.push(DrmFeedbackTranche {
|
||||||
|
device: devnum,
|
||||||
|
indices,
|
||||||
|
scanout: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tranches.extend(self.tranches.iter().cloned());
|
||||||
|
Ok(Some(Self {
|
||||||
|
id: ids.next(),
|
||||||
|
shared: self.shared.clone(),
|
||||||
|
tranches,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DrmFeedbackContext {
|
||||||
|
fn main_device(&self) -> Option<c::dev_t>;
|
||||||
|
fn for_each_read_format(&self, f: &mut dyn FnMut(u32, Modifier));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_fd_data<C: DrmFeedbackContext + ?Sized>(
|
||||||
|
ctx: &C,
|
||||||
|
) -> (Vec<u8>, AHashMap<(u32, Modifier), u16>) {
|
||||||
|
let mut vec = vec![];
|
||||||
|
let mut map = AHashMap::new();
|
||||||
|
let mut pos = 0;
|
||||||
|
ctx.for_each_read_format(&mut |format, modifier| {
|
||||||
|
vec.write_u32::<NativeEndian>(format).unwrap();
|
||||||
|
vec.write_u32::<NativeEndian>(0).unwrap();
|
||||||
|
vec.write_u64::<NativeEndian>(modifier).unwrap();
|
||||||
|
map.insert((format, modifier), pos);
|
||||||
|
pos += 1;
|
||||||
|
});
|
||||||
|
(vec, map)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum DrmFeedbackError {
|
||||||
|
#[error("Graphics API does not have a DRM device")]
|
||||||
|
NoDrmDevice,
|
||||||
|
}
|
||||||
|
|
@ -1,124 +1,17 @@
|
||||||
use {
|
pub use jay_drm_feedback::*;
|
||||||
crate::{gfx_api::GfxContext, utils::oserror::OsError, video::Modifier},
|
|
||||||
ahash::AHashMap,
|
|
||||||
byteorder::{NativeEndian, WriteBytesExt},
|
|
||||||
std::{io::Write, rc::Rc},
|
|
||||||
thiserror::Error,
|
|
||||||
uapi::{OwnedFd, c},
|
|
||||||
};
|
|
||||||
|
|
||||||
linear_ids!(DrmFeedbackIds, DrmFeedbackId);
|
use crate::{gfx_api::GfxContext, video::Modifier};
|
||||||
|
|
||||||
#[derive(Debug)]
|
impl DrmFeedbackContext for dyn GfxContext + '_ {
|
||||||
pub struct DrmFeedbackShared {
|
fn main_device(&self) -> Option<uapi::c::dev_t> {
|
||||||
pub fd: Rc<OwnedFd>,
|
self.allocator().drm().map(|drm| drm.dev())
|
||||||
pub size: usize,
|
|
||||||
pub main_device: c::dev_t,
|
|
||||||
pub indices: AHashMap<(u32, Modifier), u16>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
fn for_each_read_format(&self, f: &mut dyn FnMut(u32, Modifier)) {
|
||||||
pub struct DrmFeedback {
|
for (format, info) in &**self.formats() {
|
||||||
pub id: DrmFeedbackId,
|
|
||||||
pub shared: Rc<DrmFeedbackShared>,
|
|
||||||
pub tranches: Vec<DrmFeedbackTranche>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct DrmFeedbackTranche {
|
|
||||||
pub device: c::dev_t,
|
|
||||||
pub indices: Vec<u16>,
|
|
||||||
pub scanout: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DrmFeedback {
|
|
||||||
pub fn new(
|
|
||||||
ids: &DrmFeedbackIds,
|
|
||||||
render_ctx: &dyn GfxContext,
|
|
||||||
) -> Result<Self, DrmFeedbackError> {
|
|
||||||
let main_device = match render_ctx.allocator().drm() {
|
|
||||||
Some(drm) => drm.dev(),
|
|
||||||
_ => return Err(DrmFeedbackError::NoDrmDevice),
|
|
||||||
};
|
|
||||||
let (data, index_map) = create_fd_data(render_ctx);
|
|
||||||
let mut memfd =
|
|
||||||
uapi::memfd_create("drm_feedback", c::MFD_CLOEXEC | c::MFD_ALLOW_SEALING).unwrap();
|
|
||||||
memfd.write_all(&data).unwrap();
|
|
||||||
uapi::lseek(memfd.raw(), 0, c::SEEK_SET).unwrap();
|
|
||||||
uapi::fcntl_add_seals(
|
|
||||||
memfd.raw(),
|
|
||||||
c::F_SEAL_SEAL | c::F_SEAL_GROW | c::F_SEAL_SHRINK | c::F_SEAL_WRITE,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
Ok(Self {
|
|
||||||
id: ids.next(),
|
|
||||||
tranches: vec![DrmFeedbackTranche {
|
|
||||||
device: main_device,
|
|
||||||
indices: (0..index_map.len()).map(|v| v as u16).collect(),
|
|
||||||
scanout: false,
|
|
||||||
}],
|
|
||||||
shared: Rc::new(DrmFeedbackShared {
|
|
||||||
fd: Rc::new(memfd),
|
|
||||||
size: data.len(),
|
|
||||||
main_device,
|
|
||||||
indices: index_map,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn for_scanout(
|
|
||||||
&self,
|
|
||||||
ids: &DrmFeedbackIds,
|
|
||||||
devnum: c::dev_t,
|
|
||||||
formats: &[(u32, Modifier)],
|
|
||||||
) -> Result<Option<Self>, DrmFeedbackError> {
|
|
||||||
let mut tranches = vec![];
|
|
||||||
{
|
|
||||||
let mut indices = vec![];
|
|
||||||
for (format, modifier) in formats {
|
|
||||||
if let Some(idx) = self.shared.indices.get(&(*format, *modifier)) {
|
|
||||||
indices.push(*idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if indices.len() > 0 {
|
|
||||||
tranches.push(DrmFeedbackTranche {
|
|
||||||
device: devnum,
|
|
||||||
indices,
|
|
||||||
scanout: true,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tranches.extend(self.tranches.iter().cloned());
|
|
||||||
Ok(Some(Self {
|
|
||||||
id: ids.next(),
|
|
||||||
shared: self.shared.clone(),
|
|
||||||
tranches,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_fd_data(ctx: &dyn GfxContext) -> (Vec<u8>, AHashMap<(u32, Modifier), u16>) {
|
|
||||||
let mut vec = vec![];
|
|
||||||
let mut map = AHashMap::new();
|
|
||||||
let mut pos = 0;
|
|
||||||
for (format, info) in &**ctx.formats() {
|
|
||||||
for modifier in &info.read_modifiers {
|
for modifier in &info.read_modifiers {
|
||||||
vec.write_u32::<NativeEndian>(*format).unwrap();
|
f(*format, *modifier);
|
||||||
vec.write_u32::<NativeEndian>(0).unwrap();
|
|
||||||
vec.write_u64::<NativeEndian>(*modifier).unwrap();
|
|
||||||
map.insert((*format, *modifier), pos);
|
|
||||||
pos += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(vec, map)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum DrmFeedbackError {
|
|
||||||
#[error("Could not stat drm device")]
|
|
||||||
Stat(#[from] OsError),
|
|
||||||
#[error("Graphics API does not have a DRM device")]
|
|
||||||
NoDrmDevice,
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue