1
0
Fork 0
forked from wry/wry

video: always use correct modifiers

This commit is contained in:
Julian Orth 2023-11-04 14:06:18 +01:00
parent 283774ae4c
commit bf90204db6
17 changed files with 196 additions and 55 deletions

View file

@ -108,6 +108,14 @@ pub enum MetalError {
DevicePauseSignalHandler(#[source] DbusError), DevicePauseSignalHandler(#[source] DbusError),
#[error("Could not create device-resumed signal handler")] #[error("Could not create device-resumed signal handler")]
DeviceResumeSignalHandler(#[source] DbusError), DeviceResumeSignalHandler(#[source] DbusError),
#[error("Device render context does not support required format {0}")]
MissingDevFormat(&'static str),
#[error("Render context does not support required format {0}")]
MissingRenderFormat(&'static str),
#[error("Device cannot scan out any buffers writable by its GFX API (format {0})")]
MissingDevModifier(&'static str),
#[error("Device GFX API cannot read any buffers writable by the render GFX API (format {0})")]
MissingRenderModifier(&'static str),
} }
pub struct MetalBackend { pub struct MetalBackend {

View file

@ -28,11 +28,12 @@ use {
DRM_MODE_ATOMIC_NONBLOCK, DRM_MODE_PAGE_FLIP_EVENT, DRM_MODE_ATOMIC_NONBLOCK, DRM_MODE_PAGE_FLIP_EVENT,
}, },
gbm::{GbmDevice, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING, GBM_BO_USE_SCANOUT}, gbm::{GbmDevice, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING, GBM_BO_USE_SCANOUT},
Modifier, Modifier, INVALID_MODIFIER,
}, },
}, },
ahash::{AHashMap, AHashSet}, ahash::{AHashMap, AHashSet},
bstr::{BString, ByteSlice}, bstr::{BString, ByteSlice},
indexmap::{indexset, IndexSet},
std::{ std::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
ffi::CString, ffi::CString,
@ -508,7 +509,7 @@ pub enum PlaneType {
#[derive(Debug)] #[derive(Debug)]
pub struct PlaneFormat { pub struct PlaneFormat {
_format: &'static Format, _format: &'static Format,
modifiers: Vec<Modifier>, modifiers: IndexSet<Modifier>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -785,7 +786,7 @@ fn create_plane(plane: DrmPlane, master: &Rc<DrmMaster>) -> Result<MetalPlane, D
format, format,
PlaneFormat { PlaneFormat {
_format: f, _format: f,
modifiers: vec![], modifiers: indexset![INVALID_MODIFIER],
}, },
); );
} }
@ -1593,14 +1594,14 @@ impl MetalBackend {
&self, &self,
dev: &Rc<MetalDrmDevice>, dev: &Rc<MetalDrmDevice>,
format: &Format, format: &Format,
modifiers: &[Modifier], plane_modifiers: &IndexSet<Modifier>,
width: i32, width: i32,
height: i32, height: i32,
ctx: &MetalRenderContext, ctx: &MetalRenderContext,
cursor: bool, cursor: bool,
) -> Result<[RenderBuffer; 2], MetalError> { ) -> Result<[RenderBuffer; 2], MetalError> {
let create = let create =
|| self.create_scanout_buffer(dev, format, modifiers, width, height, ctx, cursor); || self.create_scanout_buffer(dev, format, plane_modifiers, width, height, ctx, cursor);
Ok([create()?, create()?]) Ok([create()?, create()?])
} }
@ -1608,17 +1609,35 @@ impl MetalBackend {
&self, &self,
dev: &Rc<MetalDrmDevice>, dev: &Rc<MetalDrmDevice>,
format: &Format, format: &Format,
modifiers: &[Modifier], plane_modifiers: &IndexSet<Modifier>,
width: i32, width: i32,
height: i32, height: i32,
render_ctx: &MetalRenderContext, render_ctx: &MetalRenderContext,
cursor: bool, cursor: bool,
) -> Result<RenderBuffer, MetalError> { ) -> Result<RenderBuffer, MetalError> {
let dev_gfx_formats = dev.ctx.gfx.formats();
let dev_gfx_format = match dev_gfx_formats.get(&format.drm) {
None => return Err(MetalError::MissingDevFormat(format.name)),
Some(f) => f,
};
let possible_modifiers: Vec<_> = dev_gfx_format
.write_modifiers
.iter()
.filter(|m| plane_modifiers.contains(*m))
.copied()
.collect();
if possible_modifiers.is_empty() {
log::warn!("Scanout modifiers: {:?}", plane_modifiers);
log::warn!("DEV GFX modifiers: {:?}", dev_gfx_format.write_modifiers);
return Err(MetalError::MissingDevModifier(format.name));
}
let mut usage = GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT; let mut usage = GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT;
if cursor && modifiers.is_empty() { if cursor {
usage |= GBM_BO_USE_LINEAR; usage |= GBM_BO_USE_LINEAR;
}; };
let dev_bo = dev.gbm.create_bo(width, height, format, modifiers, usage); let dev_bo = dev
.gbm
.create_bo(width, height, format, &possible_modifiers, usage);
let dev_bo = match dev_bo { let dev_bo = match dev_bo {
Ok(b) => b, Ok(b) => b,
Err(e) => return Err(MetalError::ScanoutBuffer(e)), Err(e) => return Err(MetalError::ScanoutBuffer(e)),
@ -1644,11 +1663,31 @@ impl MetalBackend {
(None, render_tex, None) (None, render_tex, None)
} else { } else {
// Create a _bridge_ BO in the render device // Create a _bridge_ BO in the render device
let render_gfx_formats = render_ctx.gfx.formats();
let render_gfx_format = match render_gfx_formats.get(&format.drm) {
None => return Err(MetalError::MissingRenderFormat(format.name)),
Some(f) => f,
};
let possible_modifiers: Vec<_> = render_gfx_format
.write_modifiers
.iter()
.filter(|m| dev_gfx_format.read_modifiers.contains(*m))
.copied()
.collect();
if possible_modifiers.is_empty() {
log::warn!(
"Render GFX modifiers: {:?}",
render_gfx_format.write_modifiers
);
log::warn!("DEV GFX modifiers: {:?}", dev_gfx_format.read_modifiers);
return Err(MetalError::MissingRenderModifier(format.name));
}
usage = GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR; usage = GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR;
let render_bo = render_ctx let render_bo =
.gfx render_ctx
.gbm() .gfx
.create_bo(width, height, format, &[], usage); .gbm()
.create_bo(width, height, format, &possible_modifiers, usage);
let render_bo = match render_bo { let render_bo = match render_bo {
Ok(b) => b, Ok(b) => b,
Err(e) => return Err(MetalError::ScanoutBuffer(e)), Err(e) => return Err(MetalError::ScanoutBuffer(e)),
@ -1765,7 +1804,7 @@ impl MetalBackend {
false, false,
)?); )?);
let mut cursor_plane = None; let mut cursor_plane = None;
let mut cursor_modifiers = &[][..]; let mut cursor_modifiers = &IndexSet::new();
for plane in crtc.possible_planes.values() { for plane in crtc.possible_planes.values() {
if plane.ty == PlaneType::Cursor if plane.ty == PlaneType::Cursor
&& !plane.assigned.get() && !plane.assigned.get()
@ -1773,7 +1812,7 @@ impl MetalBackend {
{ {
if let Some(format) = plane.formats.get(&ARGB8888.drm) { if let Some(format) = plane.formats.get(&ARGB8888.drm) {
cursor_plane = Some(plane.clone()); cursor_plane = Some(plane.clone());
cursor_modifiers = &format.modifiers[..]; cursor_modifiers = &format.modifiers;
break; break;
} }
} }

View file

@ -20,7 +20,8 @@ use {
}, },
video::{ video::{
drm::{ConnectorType, Drm, DrmError, DrmVersion}, drm::{ConnectorType, Drm, DrmError, DrmVersion},
gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING}, gbm::{GbmDevice, GbmError, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING},
INVALID_MODIFIER, LINEAR_MODIFIER,
}, },
wire_xcon::{ wire_xcon::{
ChangeProperty, ChangeWindowAttributes, ConfigureNotify, CreateCursor, CreatePixmap, ChangeProperty, ChangeWindowAttributes, ConfigureNotify, CreateCursor, CreatePixmap,
@ -117,6 +118,8 @@ pub enum XBackendError {
QueryDevice(#[source] XconError), QueryDevice(#[source] XconError),
#[error("Could not fstat the drm device")] #[error("Could not fstat the drm device")]
DrmDeviceFstat(#[source] Errno), DrmDeviceFstat(#[source] Errno),
#[error("Render device does not support XRGB8888 format")]
XRGB8888,
} }
pub async fn create(state: &Rc<State>) -> Result<Rc<XBackend>, XBackendError> { pub async fn create(state: &Rc<State>) -> Result<Rc<XBackend>, XBackendError> {
@ -376,10 +379,24 @@ impl XBackend {
height: i32, height: i32,
) -> Result<[XImage; 2], XBackendError> { ) -> Result<[XImage; 2], XBackendError> {
let mut images = [None, None]; let mut images = [None, None];
let formats = self.ctx.formats();
let format = match formats.get(&XRGB8888.drm) {
Some(f) => f,
None => return Err(XBackendError::XRGB8888),
};
let mut usage = GBM_BO_USE_RENDERING;
let modifier = if format.write_modifiers.contains(&LINEAR_MODIFIER) {
&[LINEAR_MODIFIER]
} else if format.write_modifiers.contains(&INVALID_MODIFIER) {
usage |= GBM_BO_USE_LINEAR;
&[INVALID_MODIFIER]
} else {
panic!("Neither linear nor invalid modifier is supported");
};
for image in &mut images { for image in &mut images {
let bo = self let bo = self
.gbm .gbm
.create_bo(width, height, XRGB8888, &[], GBM_BO_USE_RENDERING)?; .create_bo(width, height, XRGB8888, modifier, usage)?;
let dma = bo.dmabuf(); let dma = bo.dmabuf();
assert!(dma.planes.len() == 1); assert!(dma.planes.len() == 1);
let plane = dma.planes.first().unwrap(); let plane = dma.planes.first().unwrap();

View file

@ -8,7 +8,6 @@ use {
dmabuf::{DmaBuf, DmaBufPlane, PlaneVec}, dmabuf::{DmaBuf, DmaBufPlane, PlaneVec},
drm::Drm, drm::Drm,
gbm::{GbmDevice, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING}, gbm::{GbmDevice, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING},
INVALID_MODIFIER,
}, },
wire::{ wire::{
jay_compositor::TakeScreenshot, jay_compositor::TakeScreenshot,
@ -91,7 +90,7 @@ pub fn buf_to_qoi(buf: &Dmabuf) -> Vec<u8> {
width: buf.width as _, width: buf.width as _,
height: buf.height as _, height: buf.height as _,
format: XRGB8888, format: XRGB8888,
modifier: INVALID_MODIFIER, modifier: (buf.modifier_hi as u64) << 32 | (buf.modifier_lo as u64),
planes, planes,
}; };
let bo = match gbm.import_dmabuf(&dmabuf, GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING) { let bo = match gbm.import_dmabuf(&dmabuf, GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING) {

View file

@ -42,7 +42,7 @@ impl DrmFeedback {
fn create_fd_data(ctx: &dyn GfxContext) -> Vec<u8> { fn create_fd_data(ctx: &dyn GfxContext) -> Vec<u8> {
let mut vec = vec![]; let mut vec = vec![];
for (format, info) in &*ctx.formats() { for (format, info) in &*ctx.formats() {
for modifier in &info.modifiers { for modifier in &info.read_modifiers {
vec.write_u32::<NativeEndian>(*format).unwrap(); vec.write_u32::<NativeEndian>(*format).unwrap();
vec.write_u32::<NativeEndian>(0).unwrap(); vec.write_u32::<NativeEndian>(0).unwrap();
vec.write_u64::<NativeEndian>(*modifier).unwrap(); vec.write_u64::<NativeEndian>(*modifier).unwrap();

View file

@ -301,7 +301,8 @@ pub trait GfxContext: Debug {
#[derive(Debug)] #[derive(Debug)]
pub struct GfxFormat { pub struct GfxFormat {
pub format: &'static Format, pub format: &'static Format,
pub modifiers: IndexSet<Modifier>, pub read_modifiers: IndexSet<Modifier>,
pub write_modifiers: IndexSet<Modifier>,
} }
#[derive(Error)] #[derive(Error)]

View file

@ -151,19 +151,24 @@ impl EglDisplay {
if format.implicit_external_only && !supports_external_only { if format.implicit_external_only && !supports_external_only {
continue; continue;
} }
let mut modifiers = IndexSet::new(); let mut read_modifiers = IndexSet::new();
let mut write_modifiers = IndexSet::new();
for modifier in format.modifiers.values() { for modifier in format.modifiers.values() {
if modifier.external_only && !supports_external_only { if modifier.external_only && !supports_external_only {
continue; continue;
} }
modifiers.insert(modifier.modifier); if !modifier.external_only {
write_modifiers.insert(modifier.modifier);
}
read_modifiers.insert(modifier.modifier);
} }
if !modifiers.is_empty() { if !read_modifiers.is_empty() || !write_modifiers.is_empty() {
formats.insert( formats.insert(
drm, drm,
GfxFormat { GfxFormat {
format: format.format, format: format.format,
modifiers, read_modifiers,
write_modifiers,
}, },
); );
} }

View file

@ -143,6 +143,7 @@ impl JayCompositor {
dmabuf.height, dmabuf.height,
plane.offset, plane.offset,
plane.stride, plane.stride,
dmabuf.modifier,
); );
} }
Err(e) => { Err(e) => {

View file

@ -17,10 +17,13 @@ use {
video::{ video::{
dmabuf::DmaBuf, dmabuf::DmaBuf,
gbm::{GbmError, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING}, gbm::{GbmError, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING},
Modifier, INVALID_MODIFIER, LINEAR_MODIFIER,
}, },
wire::{jay_screencast::*, JayScreencastId}, wire::{jay_screencast::*, JayScreencastId},
}, },
ahash::AHashSet, ahash::AHashSet,
indexmap::{indexset, IndexSet},
once_cell::sync::Lazy,
std::{ std::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
@ -194,17 +197,37 @@ impl JayScreencast {
pub fn realloc(&self, ctx: &Rc<dyn GfxContext>) -> Result<(), JayScreencastError> { pub fn realloc(&self, ctx: &Rc<dyn GfxContext>) -> Result<(), JayScreencastError> {
let mut buffers = vec![]; let mut buffers = vec![];
let formats = ctx.formats();
let format = match formats.get(&XRGB8888.drm) {
Some(f) => f,
_ => return Err(JayScreencastError::XRGB8888),
};
if let Some(output) = self.output.get() { if let Some(output) = self.output.get() {
let mode = output.global.mode.get(); let mode = output.global.mode.get();
let num = 3; let num = 3;
for _ in 0..num { for _ in 0..num {
let mut flags = GBM_BO_USE_RENDERING; let mut usage = GBM_BO_USE_RENDERING;
if self.linear.get() { let modifiers = match self.linear.get() {
flags |= GBM_BO_USE_LINEAR; true if format.write_modifiers.contains(&LINEAR_MODIFIER) => {
} static MODS: Lazy<IndexSet<Modifier>> =
let buffer = ctx Lazy::new(|| indexset![LINEAR_MODIFIER]);
.gbm() &MODS
.create_bo(mode.width, mode.height, XRGB8888, &[], flags)?; }
true if format.write_modifiers.contains(&INVALID_MODIFIER) => {
usage |= GBM_BO_USE_LINEAR;
static MODS: Lazy<IndexSet<Modifier>> =
Lazy::new(|| indexset![INVALID_MODIFIER]);
&MODS
}
true => return Err(JayScreencastError::Modifier),
false if format.write_modifiers.is_empty() => {
return Err(JayScreencastError::XRGB8888Writing)
}
false => &format.write_modifiers,
};
let buffer =
ctx.gbm()
.create_bo(mode.width, mode.height, XRGB8888, modifiers, usage)?;
let fb = ctx.clone().dmabuf_img(buffer.dmabuf())?.to_framebuffer()?; let fb = ctx.clone().dmabuf_img(buffer.dmabuf())?.to_framebuffer()?;
buffers.push(ScreencastBuffer { buffers.push(ScreencastBuffer {
dmabuf: buffer.dmabuf().clone(), dmabuf: buffer.dmabuf().clone(),
@ -438,6 +461,12 @@ pub enum JayScreencastError {
GbmError(#[from] GbmError), GbmError(#[from] GbmError),
#[error(transparent)] #[error(transparent)]
GfxError(#[from] GfxError), GfxError(#[from] GfxError),
#[error("Render context does not support XRGB8888 format")]
XRGB8888,
#[error("Render context does not support XRGB8888 format for rendering")]
XRGB8888Writing,
#[error("Render context supports neither linear or invalid modifier")]
Modifier,
} }
efrom!(JayScreencastError, MsgParserError); efrom!(JayScreencastError, MsgParserError);
efrom!(JayScreencastError, ClientError); efrom!(JayScreencastError, ClientError);

View file

@ -24,6 +24,7 @@ impl JayScreenshot {
height: i32, height: i32,
offset: u32, offset: u32,
stride: u32, stride: u32,
modifier: u64,
) { ) {
self.client.event(Dmabuf { self.client.event(Dmabuf {
self_id: self.id, self_id: self.id,
@ -33,6 +34,8 @@ impl JayScreenshot {
height: height as _, height: height as _,
offset, offset,
stride, stride,
modifier_lo: modifier as u32,
modifier_hi: (modifier >> 32) as u32,
}); });
} }

View file

@ -110,7 +110,7 @@ impl ZwpLinuxBufferParamsV1 {
Some(m) => m, Some(m) => m,
_ => return Err(ZwpLinuxBufferParamsV1Error::NoPlanes), _ => return Err(ZwpLinuxBufferParamsV1Error::NoPlanes),
}; };
if !format.modifiers.contains(&modifier) { if !format.read_modifiers.contains(&modifier) {
return Err(ZwpLinuxBufferParamsV1Error::InvalidModifier(modifier)); return Err(ZwpLinuxBufferParamsV1Error::InvalidModifier(modifier));
} }
let mut dmabuf = DmaBuf { let mut dmabuf = DmaBuf {

View file

@ -44,7 +44,7 @@ impl ZwpLinuxDmabufV1Global {
for format in formats.values() { for format in formats.values() {
obj.send_format(format.format.drm); obj.send_format(format.format.drm);
if version >= MODIFIERS_SINCE_VERSION { if version >= MODIFIERS_SINCE_VERSION {
for &modifier in &format.modifiers { for &modifier in &format.read_modifiers {
obj.send_modifier(format.format.drm, modifier); obj.send_modifier(format.format.drm, modifier);
} }
} }

View file

@ -693,19 +693,32 @@ impl WindowData {
self.frame_missed.set(true); self.frame_missed.set(true);
let width = (self.width.get() as f64 * self.scale.get().to_f64()).round() as i32; let width = (self.width.get() as f64 * self.scale.get().to_f64()).round() as i32;
let height = (self.height.get() as f64 * self.scale.get().to_f64()).round() as i32; let height = (self.height.get() as f64 * self.scale.get().to_f64()).round() as i32;
let formats = ctx.ctx.formats();
let format = match formats.get(&ARGB8888.drm) {
None => {
log::error!("Render context does not support ARGB8888 format");
return;
}
Some(f) => f,
};
if format.write_modifiers.is_empty() {
log::error!("Render context cannot render to ARGB8888 format");
return;
}
for _ in 0..NUM_BUFFERS { for _ in 0..NUM_BUFFERS {
let bo = let bo = match ctx.ctx.gbm().create_bo(
match ctx width,
.ctx height,
.gbm() ARGB8888,
.create_bo(width, height, ARGB8888, &[], GBM_BO_USE_RENDERING) &format.write_modifiers,
{ GBM_BO_USE_RENDERING,
Ok(b) => b, ) {
Err(e) => { Ok(b) => b,
log::error!("Could not allocate dmabuf: {}", ErrorFmt(e)); Err(e) => {
return; log::error!("Could not allocate dmabuf: {}", ErrorFmt(e));
} return;
}; }
};
let img = match ctx.ctx.clone().dmabuf_img(bo.dmabuf()) { let img = match ctx.ctx.clone().dmabuf_img(bo.dmabuf()) {
Ok(b) => b, Ok(b) => b,
Err(e) => { Err(e) => {

View file

@ -7,6 +7,7 @@ use {
video::{ video::{
drm::DrmError, drm::DrmError,
gbm::{GbmBo, GbmError, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING}, gbm::{GbmBo, GbmError, GBM_BO_USE_LINEAR, GBM_BO_USE_RENDERING},
INVALID_MODIFIER, LINEAR_MODIFIER,
}, },
}, },
std::{ops::Deref, rc::Rc}, std::{ops::Deref, rc::Rc},
@ -26,6 +27,10 @@ pub enum ScreenshooterError {
RenderError(#[from] GfxError), RenderError(#[from] GfxError),
#[error(transparent)] #[error(transparent)]
DrmError(#[from] DrmError), DrmError(#[from] DrmError),
#[error("Render context does not support XRGB8888")]
XRGB8888,
#[error("Render context supports neither linear nor invalid modifier for XRGB8888 rendering")]
Linear,
} }
pub struct Screenshot { pub struct Screenshot {
@ -42,13 +47,24 @@ pub fn take_screenshot(state: &State) -> Result<Screenshot, ScreenshooterError>
if extents.is_empty() { if extents.is_empty() {
return Err(ScreenshooterError::EmptyDisplay); return Err(ScreenshooterError::EmptyDisplay);
} }
let formats = ctx.formats();
let mut usage = GBM_BO_USE_RENDERING;
let modifiers = match formats.get(&XRGB8888.drm) {
None => return Err(ScreenshooterError::XRGB8888),
Some(f) if f.write_modifiers.contains(&LINEAR_MODIFIER) => &[LINEAR_MODIFIER],
Some(f) if f.write_modifiers.contains(&INVALID_MODIFIER) => {
usage |= GBM_BO_USE_LINEAR;
&[INVALID_MODIFIER]
}
Some(_) => return Err(ScreenshooterError::Linear),
};
let gbm = ctx.gbm(); let gbm = ctx.gbm();
let bo = gbm.create_bo( let bo = gbm.create_bo(
extents.width(), extents.width(),
extents.height(), extents.height(),
XRGB8888, XRGB8888,
&[], modifiers,
GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR, usage,
)?; )?;
let fb = ctx.clone().dmabuf_fb(bo.dmabuf())?; let fb = ctx.clone().dmabuf_fb(bo.dmabuf())?;
fb.render_node( fb.render_node(

View file

@ -17,6 +17,7 @@ use {
}, },
ahash::AHashMap, ahash::AHashMap,
bstr::{BString, ByteSlice}, bstr::{BString, ByteSlice},
indexmap::IndexSet,
std::{ std::{
cell::RefCell, cell::RefCell,
ffi::CString, ffi::CString,
@ -181,7 +182,7 @@ impl Drm {
pub struct InFormat { pub struct InFormat {
pub format: u32, pub format: u32,
pub modifiers: Vec<Modifier>, pub modifiers: IndexSet<Modifier>,
} }
pub struct DrmMaster { pub struct DrmMaster {
@ -418,7 +419,7 @@ impl DrmMaster {
.unwrap() .unwrap()
.map(|f| InFormat { .map(|f| InFormat {
format: f, format: f,
modifiers: vec![], modifiers: IndexSet::new(),
}) })
.collect(); .collect();
let modifiers = let modifiers =
@ -435,7 +436,7 @@ impl DrmMaster {
log::error!("Modifier offset is out of bounds"); log::error!("Modifier offset is out of bounds");
return Err(DrmError::InFormats); return Err(DrmError::InFormats);
} }
formats[idx].modifiers.push(modifier.modifier); formats[idx].modifiers.insert(modifier.modifier);
} }
} }
Ok(formats) Ok(formats)

View file

@ -7,7 +7,7 @@ use {
video::{ video::{
dmabuf::{DmaBuf, DmaBufPlane, PlaneVec}, dmabuf::{DmaBuf, DmaBufPlane, PlaneVec},
drm::{Drm, DrmError}, drm::{Drm, DrmError},
Modifier, Modifier, INVALID_MODIFIER,
}, },
}, },
std::{ std::{
@ -34,6 +34,8 @@ pub enum GbmError {
DrmFd, DrmFd,
#[error("Could not map bo")] #[error("Could not map bo")]
MapBo(#[source] OsError), MapBo(#[source] OsError),
#[error("Tried to allocate a buffer with no modifier")]
NoModifier,
} }
pub type Device = u8; pub type Device = u8;
@ -195,18 +197,23 @@ impl GbmDevice {
self.dev self.dev
} }
pub fn create_bo( pub fn create_bo<'a>(
&self, &self,
width: i32, width: i32,
height: i32, height: i32,
format: &Format, format: &Format,
modifiers: &[Modifier], modifiers: impl IntoIterator<Item = &'a Modifier>,
usage: u32, mut usage: u32,
) -> Result<GbmBo, GbmError> { ) -> Result<GbmBo, GbmError> {
unsafe { unsafe {
let (modifiers, n_modifiers) = if modifiers.is_empty() { let modifiers: Vec<Modifier> = modifiers.into_iter().copied().collect();
if modifiers.is_empty() {
return Err(GbmError::NoModifier);
}
let (modifiers, n_modifiers) = if modifiers == [INVALID_MODIFIER] {
(ptr::null(), 0) (ptr::null(), 0)
} else { } else {
usage &= !GBM_BO_USE_LINEAR;
(modifiers.as_ptr() as _, modifiers.len() as _) (modifiers.as_ptr() as _, modifiers.len() as _)
}; };
let bo = gbm_bo_create_with_modifiers2( let bo = gbm_bo_create_with_modifiers2(

View file

@ -7,6 +7,8 @@ msg dmabuf = 0 {
height: u32, height: u32,
offset: u32, offset: u32,
stride: u32, stride: u32,
modifier_lo: u32,
modifier_hi: u32,
} }
msg error = 1 { msg error = 1 {