Skip to content

Commit

Permalink
swrenderer: intersect the dirty region with the screen rectangle
Browse files Browse the repository at this point in the history
When rounded out, the dirty region might end up bigger than the size
of the screen, which would then result in panic while trying to draw a
pixel out of the screen.

Fixes #6932
  • Loading branch information
ogoffart committed Nov 28, 2024
1 parent a098721 commit 9683b67
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 6 deletions.
19 changes: 19 additions & 0 deletions api/rs/slint/tests/partial_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,22 @@ fn list_view() {
}));
assert!(!window.draw_if_needed(|_| { unreachable!() }));
}

#[test]
/// test for #6932
fn scale_factor() {
slint::slint! {
export component Ui inherits Window {
}
}

slint::platform::set_platform(Box::new(TestPlatform)).ok();
let ui = Ui::new().unwrap();
let window = WINDOW.with(|x| x.clone());
window.set_size(slint::PhysicalSize::new(500, 500));
window.dispatch_event(slint::platform::WindowEvent::ScaleFactorChanged { scale_factor: 1.33 });
ui.show().unwrap();
assert!(window.draw_if_needed(|renderer| {
do_test_render_region(renderer, 0, 0, 500, 500);
}));
}
25 changes: 19 additions & 6 deletions internal/core/software_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,8 +503,15 @@ impl SoftwareRenderer {
logical_size,
);
let rotation = RotationInfo { orientation: rotation, screen_size: size };
let mut i = renderer.dirty_region.iter().map(|r| {
(r.cast() * factor).to_rect().round_out().cast().transformed(rotation)
let screen_rect = PhysicalRect::from_size(size);
let mut i = renderer.dirty_region.iter().filter_map(|r| {
(r.cast() * factor)
.to_rect()
.round_out()
.cast()
.intersection(&screen_rect)?
.transformed(rotation)
.into()
});
let dirty_region = PhysicalRegion {
rectangles: core::array::from_fn(|_| i.next().unwrap_or_default().to_box2d()),
Expand Down Expand Up @@ -973,10 +980,16 @@ fn prepare_scene(
);
let rotation =
RotationInfo { orientation: software_renderer.rotation.get(), screen_size: size };
let mut i = renderer
.dirty_region
.iter()
.map(|r| (r.cast() * factor).to_rect().round_out().cast().transformed(rotation));
let screen_rect = PhysicalRect::from_size(size);
let mut i = renderer.dirty_region.iter().filter_map(|r| {
(r.cast() * factor)
.to_rect()
.round_out()
.cast()
.intersection(&screen_rect)?
.transformed(rotation)
.into()
});
dirty_region = PhysicalRegion {
rectangles: core::array::from_fn(|_| i.next().unwrap_or_default().to_box2d()),
count: renderer.dirty_region.iter().count(),
Expand Down

0 comments on commit 9683b67

Please sign in to comment.