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.
This commit is contained in:
1 parent
a2be421974
commit
993bc0f88f
391 files changed
+130908
-76
No files matched your search
+203
@@ -0,0 +1,203 @@
|
||||
//! 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(),
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user