Files
feresaria/vendor/smithay/src/backend/drm/dumb.rs
T
aria 993bc0f88f Integrate native Rime and stabilize input, output, and rendering
- Add optional modifier-only Super binding whose tap is cancelled by
  other input, focus changes, grabs, locks, and session teardown.
- Ship the native ferese-rime user service, Rime defaults, installer
  inventory, package dependencies, session environment, and docs.
- Vendor Smithay 8a27023 with the SHM texture-cache format fix and add
  GPU regressions for format changes and resize snapshots.
- Release reused CRTC owners before staging output modes, then restore
  changed outputs before former owners when a transaction fails.
- Wait for resize-capture GPU completion, expand filtered surface
  damage, and preserve IME popup origin under fractional scaling.
- Mark weekends like holidays in both calendar layouts.
2026-10-30 03:13:43 +09:00

204 lines
4.7 KiB
Rust

//! Utilities to attach [`framebuffer::Handle`]s to dumb buffers
use drm_fourcc::{DrmFormat, DrmModifier};
use drm::{
buffer::{Buffer as DrmBuffer, PlanarBuffer},
control::{Device, FbCmd2Flags, framebuffer},
};
use tracing::{trace, warn};
use crate::utils::DevPath;
use crate::{
backend::{
allocator::{
Buffer, Fourcc,
dumb::DumbBuffer,
format::{get_bpp, get_depth, get_opaque},
},
drm::DrmDeviceFd,
},
utils::{Buffer as BufferCoords, Size},
};
use super::{Framebuffer, error::AccessError, warn_legacy_fb_export};
/// A GBM backed framebuffer
#[derive(Debug)]
pub struct DumbFramebuffer {
fb: framebuffer::Handle,
format: drm_fourcc::DrmFormat,
drm: DrmDeviceFd,
}
impl Drop for DumbFramebuffer {
fn drop(&mut self) {
trace!(fb = ?self.fb, "destroying framebuffer");
if let Err(err) = self.drm.destroy_framebuffer(self.fb) {
warn!(fb = ?self.fb, ?err, "failed to destroy framebuffer");
}
}
}
impl AsRef<framebuffer::Handle> for DumbFramebuffer {
#[inline]
fn as_ref(&self) -> &framebuffer::Handle {
&self.fb
}
}
impl Framebuffer for DumbFramebuffer {
#[inline]
fn format(&self) -> drm_fourcc::DrmFormat {
self.format
}
}
struct PlanarDumbBuffer<'a>(&'a DumbBuffer);
impl Buffer for PlanarDumbBuffer<'_> {
#[inline]
fn size(&self) -> Size<i32, BufferCoords> {
self.0.size()
}
#[inline]
fn format(&self) -> DrmFormat {
self.0.format()
}
}
impl PlanarBuffer for PlanarDumbBuffer<'_> {
#[inline]
fn size(&self) -> (u32, u32) {
let size = self.0.size();
(size.w as u32, size.h as u32)
}
#[inline]
fn format(&self) -> Fourcc {
self.0.format().code
}
#[inline]
fn modifier(&self) -> Option<DrmModifier> {
Some(self.0.format().modifier)
}
#[inline]
fn pitches(&self) -> [u32; 4] {
[self.0.handle().pitch(), 0, 0, 0]
}
#[inline]
fn handles(&self) -> [Option<drm::buffer::Handle>; 4] {
[Some(self.0.handle().handle()), None, None, None]
}
#[inline]
fn offsets(&self) -> [u32; 4] {
[0, 0, 0, 0]
}
}
struct OpaqueBufferWrapper<'a, B>(&'a B);
impl<B> PlanarBuffer for OpaqueBufferWrapper<'_, B>
where
B: PlanarBuffer,
{
#[inline]
fn size(&self) -> (u32, u32) {
self.0.size()
}
#[inline]
fn format(&self) -> Fourcc {
let fmt = self.0.format();
get_opaque(fmt).unwrap_or(fmt)
}
#[inline]
fn modifier(&self) -> Option<DrmModifier> {
self.0.modifier()
}
#[inline]
fn pitches(&self) -> [u32; 4] {
self.0.pitches()
}
#[inline]
fn handles(&self) -> [Option<drm::buffer::Handle>; 4] {
self.0.handles()
}
#[inline]
fn offsets(&self) -> [u32; 4] {
self.0.offsets()
}
}
/// Attach a [`framebuffer::Handle`] to an [`DumbBuffer`]
#[profiling::function]
pub fn framebuffer_from_dumb_buffer(
drm: &DrmDeviceFd,
buffer: &DumbBuffer,
use_opaque: bool,
) -> Result<DumbFramebuffer, AccessError> {
let buffer = PlanarDumbBuffer(buffer);
let format = Buffer::format(&buffer);
let modifier = buffer.modifier();
let flags = if modifier.is_some() {
FbCmd2Flags::MODIFIERS
} else {
FbCmd2Flags::empty()
};
let ret = if use_opaque {
let opaque_wrapper = OpaqueBufferWrapper(&buffer);
drm.add_planar_framebuffer(&opaque_wrapper, flags).map(|fb| {
(
fb,
drm_fourcc::DrmFormat {
code: opaque_wrapper.format(),
modifier: modifier.unwrap_or(DrmModifier::Invalid),
},
)
})
} else {
drm.add_planar_framebuffer(&buffer, flags).map(|fb| (fb, format))
};
let (fb, format) = match ret {
Ok(fb) => fb,
Err(source) => {
warn_legacy_fb_export();
let fourcc = format.code;
let (depth, bpp) = get_depth(fourcc)
.zip(get_bpp(fourcc))
.ok_or_else(|| AccessError {
errmsg: "Unknown format for legacy framebuffer",
dev: drm.dev_path(),
source,
})?;
let fb = drm
.add_framebuffer(buffer.0.handle(), depth as u32, bpp as u32)
.map_err(|source| AccessError {
errmsg: "Failed to add framebuffer",
dev: drm.dev_path(),
source,
})?;
(fb, format)
}
};
Ok(DumbFramebuffer {
fb,
format,
drm: drm.clone(),
})
}