1
0
Fork 0
forked from wry/wry

drm_feedback: move table generation into workspace crate

This commit is contained in:
kossLAN 2026-05-29 11:51:32 -04:00
parent 6d569bd4b7
commit 81a718aa74
No known key found for this signature in database
5 changed files with 185 additions and 116 deletions

12
Cargo.lock generated
View file

@ -731,6 +731,7 @@ dependencies = [
"jay-cpu-worker",
"jay-criteria",
"jay-dbus-core",
"jay-drm-feedback",
"jay-edid",
"jay-eventfd-cache",
"jay-formats",
@ -840,6 +841,17 @@ dependencies = [
"uapi",
]
[[package]]
name = "jay-drm-feedback"
version = "0.1.0"
dependencies = [
"ahash",
"byteorder",
"jay-video-types",
"thiserror",
"uapi",
]
[[package]]
name = "jay-edid"
version = "0.1.0"

View file

@ -48,6 +48,7 @@ members = [
"clientmem",
"allocator",
"output-schedule",
"drm-feedback",
"pango",
"libinput",
"toml-config",
@ -99,6 +100,7 @@ jay-theme = { version = "0.1.0", path = "theme" }
jay-clientmem = { version = "0.1.0", path = "clientmem" }
jay-allocator = { version = "0.1.0", path = "allocator" }
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-libinput = { version = "0.1.0", path = "libinput" }

13
drm-feedback/Cargo.toml Normal file
View 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
View 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,
}

View file

@ -1,124 +1,17 @@
use {
crate::{gfx_api::GfxContext, utils::oserror::OsError, video::Modifier},
ahash::AHashMap,
byteorder::{NativeEndian, WriteBytesExt},
std::{io::Write, rc::Rc},
thiserror::Error,
uapi::{OwnedFd, c},
};
pub use jay_drm_feedback::*;
linear_ids!(DrmFeedbackIds, DrmFeedbackId);
use crate::{gfx_api::GfxContext, video::Modifier};
#[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(
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,
}),
})
impl DrmFeedbackContext for dyn GfxContext + '_ {
fn main_device(&self) -> Option<uapi::c::dev_t> {
self.allocator().drm().map(|drm| drm.dev())
}
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);
fn for_each_read_format(&self, f: &mut dyn FnMut(u32, Modifier)) {
for (format, info) in &**self.formats() {
for modifier in &info.read_modifiers {
f(*format, *modifier);
}
}
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 {
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("Could not stat drm device")]
Stat(#[from] OsError),
#[error("Graphics API does not have a DRM device")]
NoDrmDevice,
}