gbm: Force implicit modifiers for old api

Buffers created via `gbm_bo_create` might return (errornous or actual) modifiers, which can then lead to errors trying to attach them to drm or exporting in dmabuf, which will then suddenly have modifiers.

So lets track if the creation method allows for modifiers or not.
This commit is contained in:
Victoria Brekenfeld 2024-05-16 11:21:39 +02:00
parent f25bcd892e
commit 62edd3c3fc
2 changed files with 26 additions and 15 deletions

View file

@ -87,11 +87,21 @@ impl drm::buffer::Buffer for GbmBuffer {
impl GbmBuffer { impl GbmBuffer {
/// Create a [`GbmBuffer`] from an existing [`BufferObject`] /// Create a [`GbmBuffer`] from an existing [`BufferObject`]
pub fn from_bo(bo: BufferObject<()>) -> Self { ///
/// `implicit` forces the object to assume the modifier is `Invalid` for cases,
/// where the buffer was allocated with an older api, that doesn't support modifiers.
///
/// Gbm might otherwise give us the underlying or a non-sensical modifier,
/// which can fail in various other apis.
pub fn from_bo(bo: BufferObject<()>, implicit: bool) -> Self {
let size = (bo.width().unwrap_or(0) as i32, bo.height().unwrap_or(0) as i32).into(); let size = (bo.width().unwrap_or(0) as i32, bo.height().unwrap_or(0) as i32).into();
let format = Format { let format = Format {
code: bo.format().unwrap_or(Fourcc::Argb8888), // we got to return something, but this should never happen anyway code: bo.format().unwrap_or(Fourcc::Argb8888), // we got to return something, but this should never happen anyway
modifier: bo.modifier().unwrap_or(Modifier::Invalid), modifier: if implicit {
Modifier::Invalid
} else {
bo.modifier().unwrap_or(Modifier::Invalid)
},
}; };
Self { bo, size, format } Self { bo, size, format }
} }
@ -164,20 +174,21 @@ impl<A: AsFd + 'static> GbmAllocator<A> {
flags: GbmBufferFlags, flags: GbmBufferFlags,
) -> Result<GbmBuffer, std::io::Error> { ) -> Result<GbmBuffer, std::io::Error> {
#[cfg(feature = "backend_gbm_has_create_with_modifiers2")] #[cfg(feature = "backend_gbm_has_create_with_modifiers2")]
let result = self.device.create_buffer_object_with_modifiers2( let result = self
width, .device
height, .create_buffer_object_with_modifiers2(width, height, fourcc, modifiers.iter().copied(), flags)
fourcc, .map(|bo| GbmBuffer::from_bo(bo, false));
modifiers.iter().copied(),
flags,
);
#[cfg(not(feature = "backend_gbm_has_create_with_modifiers2"))] #[cfg(not(feature = "backend_gbm_has_create_with_modifiers2"))]
let result = if (flags & !(GbmBufferFlags::SCANOUT | GbmBufferFlags::RENDERING)).is_empty() { let result = if (flags & !(GbmBufferFlags::SCANOUT | GbmBufferFlags::RENDERING)).is_empty() {
self.device self.device
.create_buffer_object_with_modifiers(width, height, fourcc, modifiers.iter().copied()) .create_buffer_object_with_modifiers(width, height, fourcc, modifiers.iter().copied())
.map(|bo| GbmBuffer::from_bo(bo, false))
} else if modifiers.contains(&Modifier::Invalid) || modifiers.contains(&Modifier::Linear) { } else if modifiers.contains(&Modifier::Invalid) || modifiers.contains(&Modifier::Linear) {
return self.device.create_buffer_object(width, height, fourcc, flags); return self
.device
.create_buffer_object(width, height, fourcc, flags)
.map(|bo| GbmBuffer::from_bo(bo, true));
} else { } else {
return Err(std::io::Error::new( return Err(std::io::Error::new(
std::io::ErrorKind::Other, std::io::ErrorKind::Other,
@ -186,12 +197,12 @@ impl<A: AsFd + 'static> GbmAllocator<A> {
}; };
match result { match result {
Ok(bo) => Ok(GbmBuffer::from_bo(bo)), Ok(bo) => Ok(bo),
Err(err) => { Err(err) => {
if modifiers.contains(&Modifier::Invalid) || modifiers.contains(&Modifier::Linear) { if modifiers.contains(&Modifier::Invalid) || modifiers.contains(&Modifier::Linear) {
self.device self.device
.create_buffer_object(width, height, fourcc, flags) .create_buffer_object(width, height, fourcc, flags)
.map(GbmBuffer::from_bo) .map(|bo| GbmBuffer::from_bo(bo, true))
} else { } else {
Err(err) Err(err)
} }
@ -360,7 +371,7 @@ impl Dmabuf {
offsets, offsets,
self.format().modifier, self.format().modifier,
) )
.map(GbmBuffer::from_bo) .map(|bo| GbmBuffer::from_bo(bo, false))
} else { } else {
gbm.import_buffer_object_from_dma_buf( gbm.import_buffer_object_from_dma_buf(
handles[0].unwrap(), handles[0].unwrap(),
@ -374,7 +385,7 @@ impl Dmabuf {
usage usage
}, },
) )
.map(GbmBuffer::from_bo) .map(|bo| GbmBuffer::from_bo(bo, true))
} }
} }
} }

View file

@ -96,7 +96,7 @@ pub fn framebuffer_from_wayland_buffer<A: AsFd + 'static>(
) { ) {
let bo = gbm let bo = gbm
.import_buffer_object_from_wayland::<()>(buffer, gbm::BufferObjectFlags::SCANOUT) .import_buffer_object_from_wayland::<()>(buffer, gbm::BufferObjectFlags::SCANOUT)
.map(GbmBuffer::from_bo) .map(|bo| GbmBuffer::from_bo(bo, true))
.map_err(Error::Import)?; .map_err(Error::Import)?;
let (fb, format) = framebuffer_from_bo_internal( let (fb, format) = framebuffer_from_bo_internal(
drm, drm,