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
@@ -0,0 +1,182 @@
|
||||
//! Compare damaged swapchain frames with an independently repainted scene.
|
||||
use super::*;
|
||||
use smithay::backend::renderer::damage::OutputDamageTracker;
|
||||
use smithay::backend::renderer::element::solid::SolidColorBuffer;
|
||||
use smithay::utils::user_data::UserDataMap;
|
||||
|
||||
fn blur(
|
||||
renderer: &mut GlesRenderer,
|
||||
program: &BlurProgram,
|
||||
scale: f64,
|
||||
size: Size<i32, Physical>,
|
||||
transform: Transform,
|
||||
) -> BlurRenderElement {
|
||||
let sample = Rectangle::<i32, Logical>::new((0, 10).into(), (145, 80).into());
|
||||
let visible = Rectangle::<i32, Logical>::new((10, 20).into(), (120, 55).into());
|
||||
let sample_physical = sample.to_physical_precise_round(scale);
|
||||
let framebuffer = framebuffer_clip_rect(sample_physical, size, transform.invert());
|
||||
let capture = framebuffer_capture_rect(framebuffer);
|
||||
let texture = renderer
|
||||
.create_buffer(Fourcc::Abgr8888, (capture[2], capture[3]).into())
|
||||
.unwrap();
|
||||
BlurRenderElement::new(
|
||||
texture,
|
||||
program.0.clone(),
|
||||
&MaterialParameters {
|
||||
panel: None,
|
||||
corner_radii: [0.; 4],
|
||||
presentation_alpha: 1.,
|
||||
background_opacity: 0.,
|
||||
blur: (8. * scale) as f32,
|
||||
sample_geometry: sample,
|
||||
sample_physical,
|
||||
sample_framebuffer: framebuffer,
|
||||
shadow_rect: [0.; 4],
|
||||
shadow_values: [0.; 2],
|
||||
shadow_bounds: visible,
|
||||
geometry: visible,
|
||||
tint: [0.; 4],
|
||||
generation: 0,
|
||||
opaque: false,
|
||||
visible_framebuffer: framebuffer_clip_rect(
|
||||
visible.to_physical_precise_round(scale),
|
||||
size,
|
||||
transform.invert(),
|
||||
),
|
||||
},
|
||||
Arc::new(AtomicBool::new(true)),
|
||||
)
|
||||
}
|
||||
|
||||
fn pixels(renderer: &mut GlesRenderer, texture: &mut GlesTexture) -> Vec<u8> {
|
||||
let size = texture.size();
|
||||
let target = renderer.bind(texture).unwrap();
|
||||
let mapping = renderer
|
||||
.copy_framebuffer(&target, Rectangle::from_size(size), Fourcc::Abgr8888)
|
||||
.unwrap();
|
||||
renderer.map_texture(&mapping).unwrap().to_vec()
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires an EGL rendering device"]
|
||||
fn blur_behind_moving_opaque_window_matches_full_frames_at_buffer_age_three() {
|
||||
let mut renderer = {
|
||||
use smithay::backend::egl::{EGLContext, EGLDevice, EGLDisplay};
|
||||
let software = std::env::var_os("FERESE_TEST_EGL_SOFTWARE").is_some();
|
||||
let device = EGLDevice::enumerate()
|
||||
.unwrap()
|
||||
.find(|device| device.is_software() == software)
|
||||
.unwrap();
|
||||
// SAFETY: The enumerated device remains owned by the EGL display/context.
|
||||
let display = unsafe { EGLDisplay::new(device).unwrap() };
|
||||
// SAFETY: This test owns the renderer's fresh context exclusively.
|
||||
unsafe { GlesRenderer::new(EGLContext::new(&display).unwrap()).unwrap() }
|
||||
};
|
||||
let mut resources = RenderResources::default();
|
||||
let program = blur_program(&mut resources, &mut renderer).unwrap();
|
||||
for scale in [1., 1.5, 2.] {
|
||||
for transform in [Transform::Normal, Transform::Flipped180] {
|
||||
let size: Size<i32, Physical> = ((160. * scale) as i32, (100. * scale) as i32).into();
|
||||
let mut tracker = OutputDamageTracker::new(size, scale, transform);
|
||||
let mut targets = (0..3)
|
||||
.map(|_| {
|
||||
renderer
|
||||
.create_buffer(Fourcc::Abgr8888, (size.w, size.h).into())
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<Vec<GlesTexture>>();
|
||||
let mut reference: GlesTexture = renderer
|
||||
.create_buffer(Fourcc::Abgr8888, (size.w, size.h).into())
|
||||
.unwrap();
|
||||
let effect = blur(&mut renderer, &program, scale, size, transform);
|
||||
let mut background = SolidColorBuffer::new((160, 100), [0.1, 0.7, 0.2, 1.]);
|
||||
let foreground = SolidColorBuffer::new((60, 90), [0.2, 0.1, 0.8, 1.]);
|
||||
for frame_index in 0..9 {
|
||||
if frame_index % 3 == 0 {
|
||||
background.set_color([0.1, 0.3 + frame_index as f32 * 0.05, 0.2, 1.]);
|
||||
}
|
||||
let solid = || {
|
||||
SolidColorRenderElement::from_buffer(
|
||||
&background,
|
||||
(0, 0),
|
||||
scale,
|
||||
1.,
|
||||
RenderElementKind::Unspecified,
|
||||
)
|
||||
};
|
||||
let front = SolidColorRenderElement::from_buffer(
|
||||
&foreground,
|
||||
(((100 - frame_index * 3) as f64 * scale) as i32, 0),
|
||||
scale,
|
||||
1.,
|
||||
RenderElementKind::Unspecified,
|
||||
);
|
||||
let elements: Vec<AnimatedWindowRenderElement> =
|
||||
vec![front.clone().into(), effect.clone().into(), solid().into()];
|
||||
backdrop::update(&elements, scale);
|
||||
let slot = frame_index as usize % 3;
|
||||
{
|
||||
let mut target = renderer.bind(&mut targets[slot]).unwrap();
|
||||
tracker
|
||||
.render_output(
|
||||
&mut renderer,
|
||||
&mut target,
|
||||
if frame_index < 3 { 0 } else { 3 },
|
||||
&elements,
|
||||
Color32F::TRANSPARENT,
|
||||
)
|
||||
.unwrap()
|
||||
.sync
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Paint every layer without opaque culling or damage reuse.
|
||||
// A separate capture texture prevents the oracle from repairing
|
||||
// the incremental renderer's cached copy as a side effect.
|
||||
let reference_blur = blur(&mut renderer, &program, scale, size, transform);
|
||||
let full_elements: Vec<AnimatedWindowRenderElement> =
|
||||
vec![front.into(), reference_blur.into(), solid().into()];
|
||||
{
|
||||
let mut target = renderer.bind(&mut reference).unwrap();
|
||||
let mut frame = renderer
|
||||
.render(&mut target, size, transform.invert())
|
||||
.unwrap();
|
||||
let full = Rectangle::from_size(size);
|
||||
frame.clear(Color32F::TRANSPARENT, &[full]).unwrap();
|
||||
for element in full_elements.iter().rev() {
|
||||
let cache = UserDataMap::default();
|
||||
let rect = element.geometry(scale.into());
|
||||
if element.is_framebuffer_effect() {
|
||||
element
|
||||
.capture_framebuffer(&mut frame, element.src(), rect, &cache)
|
||||
.unwrap();
|
||||
}
|
||||
element
|
||||
.draw(
|
||||
&mut frame,
|
||||
element.src(),
|
||||
rect,
|
||||
&[Rectangle::from_size(rect.size)],
|
||||
&[],
|
||||
element.is_framebuffer_effect().then_some(&cache),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
frame.finish().unwrap().wait().unwrap();
|
||||
}
|
||||
let actual = pixels(&mut renderer, &mut targets[slot]);
|
||||
let expected = pixels(&mut renderer, &mut reference);
|
||||
let differing = actual
|
||||
.iter()
|
||||
.zip(&expected)
|
||||
.filter(|(a, b)| a.abs_diff(**b) > 1)
|
||||
.count();
|
||||
assert_eq!(
|
||||
differing, 0,
|
||||
"scale={scale} transform={transform:?} frame={frame_index}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user