Keep playing with incremental rendering (still very slow)
This commit is contained in:
parent
0f7abffc0e
commit
6270c33ed9
2 changed files with 161 additions and 85 deletions
|
|
@ -230,7 +230,11 @@ impl Primitive {
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
if bounds_a == bounds_b {
|
if bounds_a == bounds_b {
|
||||||
return content_a.damage(content_b);
|
return content_a
|
||||||
|
.damage(content_b)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|r| r.intersection(bounds_a))
|
||||||
|
.collect();
|
||||||
} else {
|
} else {
|
||||||
return vec![*bounds_a, *bounds_b];
|
return vec![*bounds_a, *bounds_b];
|
||||||
}
|
}
|
||||||
|
|
@ -246,7 +250,11 @@ impl Primitive {
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
if translation_a == translation_b {
|
if translation_a == translation_b {
|
||||||
return content_a.damage(content_b);
|
return content_a
|
||||||
|
.damage(content_b)
|
||||||
|
.into_iter()
|
||||||
|
.map(|r| r + *translation_a)
|
||||||
|
.collect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ pub struct Backend {
|
||||||
|
|
||||||
last_primitives: Vec<Primitive>,
|
last_primitives: Vec<Primitive>,
|
||||||
last_background_color: Color,
|
last_background_color: Color,
|
||||||
|
last_size: Size<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backend {
|
impl Backend {
|
||||||
|
|
@ -37,6 +38,7 @@ impl Backend {
|
||||||
|
|
||||||
last_primitives: Vec::new(),
|
last_primitives: Vec::new(),
|
||||||
last_background_color: Color::BLACK,
|
last_background_color: Color::BLACK,
|
||||||
|
last_size: Size::new(0, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,9 +49,13 @@ impl Backend {
|
||||||
primitives: &[Primitive],
|
primitives: &[Primitive],
|
||||||
viewport: &Viewport,
|
viewport: &Viewport,
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
overlay: &[T],
|
_overlay: &[T],
|
||||||
) {
|
) {
|
||||||
let damage = if self.last_background_color == background_color {
|
let physical_size = viewport.physical_size();
|
||||||
|
|
||||||
|
let damage = if self.last_background_color == background_color
|
||||||
|
&& self.last_size == physical_size
|
||||||
|
{
|
||||||
Primitive::damage_list(&self.last_primitives, primitives)
|
Primitive::damage_list(&self.last_primitives, primitives)
|
||||||
} else {
|
} else {
|
||||||
vec![Rectangle::with_size(viewport.logical_size())]
|
vec![Rectangle::with_size(viewport.logical_size())]
|
||||||
|
|
@ -61,24 +67,46 @@ impl Backend {
|
||||||
|
|
||||||
self.last_primitives = primitives.to_vec();
|
self.last_primitives = primitives.to_vec();
|
||||||
self.last_background_color = background_color;
|
self.last_background_color = background_color;
|
||||||
|
self.last_size = physical_size;
|
||||||
|
|
||||||
let scale_factor = viewport.scale_factor() as f32;
|
let scale_factor = viewport.scale_factor() as f32;
|
||||||
|
let physical_bounds = Rectangle {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
width: physical_size.width as f32,
|
||||||
|
height: physical_size.height as f32,
|
||||||
|
};
|
||||||
|
|
||||||
dbg!(&damage);
|
dbg!(damage.len());
|
||||||
|
|
||||||
|
'draw_regions: for (i, region) in damage.iter().enumerate() {
|
||||||
|
for previous in damage.iter().take(i) {
|
||||||
|
if previous.contains(region.position())
|
||||||
|
&& previous.contains(
|
||||||
|
region.position()
|
||||||
|
+ Vector::new(region.width, region.height),
|
||||||
|
)
|
||||||
|
{
|
||||||
|
continue 'draw_regions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for region in &damage {
|
|
||||||
let region = *region * scale_factor;
|
let region = *region * scale_factor;
|
||||||
|
|
||||||
|
let Some(region) = physical_bounds.intersection(®ion) else { continue };
|
||||||
|
|
||||||
|
let path = tiny_skia::PathBuilder::from_rect(
|
||||||
|
tiny_skia::Rect::from_xywh(
|
||||||
|
region.x,
|
||||||
|
region.y,
|
||||||
|
region.width.min(viewport.physical_width() as f32),
|
||||||
|
region.height.min(viewport.physical_height() as f32),
|
||||||
|
)
|
||||||
|
.expect("Create damage rectangle"),
|
||||||
|
);
|
||||||
|
|
||||||
pixels.fill_path(
|
pixels.fill_path(
|
||||||
&tiny_skia::PathBuilder::from_rect(
|
&path,
|
||||||
tiny_skia::Rect::from_xywh(
|
|
||||||
region.x,
|
|
||||||
region.y,
|
|
||||||
region.width.min(viewport.physical_width() as f32),
|
|
||||||
region.height.min(viewport.physical_height() as f32),
|
|
||||||
)
|
|
||||||
.expect("Create damage rectangle"),
|
|
||||||
),
|
|
||||||
&tiny_skia::Paint {
|
&tiny_skia::Paint {
|
||||||
shader: tiny_skia::Shader::SolidColor(into_color(
|
shader: tiny_skia::Shader::SolidColor(into_color(
|
||||||
background_color,
|
background_color,
|
||||||
|
|
@ -89,46 +117,63 @@ impl Backend {
|
||||||
tiny_skia::Transform::identity(),
|
tiny_skia::Transform::identity(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
adjust_clip_mask(clip_mask, pixels, region);
|
||||||
|
|
||||||
|
for primitive in primitives {
|
||||||
|
self.draw_primitive(
|
||||||
|
primitive,
|
||||||
|
pixels,
|
||||||
|
clip_mask,
|
||||||
|
region,
|
||||||
|
scale_factor,
|
||||||
|
Vector::ZERO,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//pixels.stroke_path(
|
||||||
|
// &path,
|
||||||
|
// &tiny_skia::Paint {
|
||||||
|
// shader: tiny_skia::Shader::SolidColor(into_color(
|
||||||
|
// Color::from_rgb(1.0, 0.0, 0.0),
|
||||||
|
// )),
|
||||||
|
// anti_alias: true,
|
||||||
|
// ..tiny_skia::Paint::default()
|
||||||
|
// },
|
||||||
|
// &tiny_skia::Stroke {
|
||||||
|
// width: 1.0,
|
||||||
|
// ..tiny_skia::Stroke::default()
|
||||||
|
// },
|
||||||
|
// tiny_skia::Transform::identity(),
|
||||||
|
// None,
|
||||||
|
//);
|
||||||
}
|
}
|
||||||
|
|
||||||
for primitive in primitives {
|
//for (i, text) in overlay.iter().enumerate() {
|
||||||
self.draw_primitive(
|
// const OVERLAY_TEXT_SIZE: f32 = 20.0;
|
||||||
primitive,
|
|
||||||
pixels,
|
|
||||||
clip_mask,
|
|
||||||
None,
|
|
||||||
scale_factor,
|
|
||||||
Vector::ZERO,
|
|
||||||
&damage,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, text) in overlay.iter().enumerate() {
|
// self.draw_primitive(
|
||||||
const OVERLAY_TEXT_SIZE: f32 = 20.0;
|
// &Primitive::Text {
|
||||||
|
// content: text.as_ref().to_owned(),
|
||||||
self.draw_primitive(
|
// size: OVERLAY_TEXT_SIZE,
|
||||||
&Primitive::Text {
|
// bounds: Rectangle {
|
||||||
content: text.as_ref().to_owned(),
|
// x: 10.0,
|
||||||
size: OVERLAY_TEXT_SIZE,
|
// y: 10.0 + i as f32 * OVERLAY_TEXT_SIZE * 1.2,
|
||||||
bounds: Rectangle {
|
// width: f32::INFINITY,
|
||||||
x: 10.0,
|
// height: f32::INFINITY,
|
||||||
y: 10.0 + i as f32 * OVERLAY_TEXT_SIZE * 1.2,
|
// },
|
||||||
width: f32::INFINITY,
|
// color: Color::BLACK,
|
||||||
height: f32::INFINITY,
|
// font: Font::MONOSPACE,
|
||||||
},
|
// horizontal_alignment: alignment::Horizontal::Left,
|
||||||
color: Color::BLACK,
|
// vertical_alignment: alignment::Vertical::Top,
|
||||||
font: Font::MONOSPACE,
|
// },
|
||||||
horizontal_alignment: alignment::Horizontal::Left,
|
// pixels,
|
||||||
vertical_alignment: alignment::Vertical::Top,
|
// clip_mask,
|
||||||
},
|
// Rectangle::EMPTY,
|
||||||
pixels,
|
// scale_factor,
|
||||||
clip_mask,
|
// Vector::ZERO,
|
||||||
None,
|
// );
|
||||||
scale_factor,
|
//}
|
||||||
Vector::ZERO,
|
|
||||||
&[],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.text_pipeline.trim_cache();
|
self.text_pipeline.trim_cache();
|
||||||
|
|
||||||
|
|
@ -144,10 +189,9 @@ impl Backend {
|
||||||
primitive: &Primitive,
|
primitive: &Primitive,
|
||||||
pixels: &mut tiny_skia::PixmapMut<'_>,
|
pixels: &mut tiny_skia::PixmapMut<'_>,
|
||||||
clip_mask: &mut tiny_skia::ClipMask,
|
clip_mask: &mut tiny_skia::ClipMask,
|
||||||
clip_bounds: Option<Rectangle>,
|
clip_bounds: Rectangle,
|
||||||
scale_factor: f32,
|
scale_factor: f32,
|
||||||
translation: Vector,
|
translation: Vector,
|
||||||
damage: &[Rectangle],
|
|
||||||
) {
|
) {
|
||||||
match primitive {
|
match primitive {
|
||||||
Primitive::Quad {
|
Primitive::Quad {
|
||||||
|
|
@ -157,7 +201,9 @@ impl Backend {
|
||||||
border_width,
|
border_width,
|
||||||
border_color,
|
border_color,
|
||||||
} => {
|
} => {
|
||||||
if !damage.iter().any(|damage| damage.intersects(bounds)) {
|
if !clip_bounds
|
||||||
|
.intersects(&((*bounds + translation) * scale_factor))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,7 +214,6 @@ impl Backend {
|
||||||
.post_scale(scale_factor, scale_factor);
|
.post_scale(scale_factor, scale_factor);
|
||||||
|
|
||||||
let path = rounded_rectangle(*bounds, *border_radius);
|
let path = rounded_rectangle(*bounds, *border_radius);
|
||||||
let clip_mask = clip_bounds.map(|_| clip_mask as &_);
|
|
||||||
|
|
||||||
pixels.fill_path(
|
pixels.fill_path(
|
||||||
&path,
|
&path,
|
||||||
|
|
@ -185,7 +230,7 @@ impl Backend {
|
||||||
},
|
},
|
||||||
tiny_skia::FillRule::EvenOdd,
|
tiny_skia::FillRule::EvenOdd,
|
||||||
transform,
|
transform,
|
||||||
clip_mask,
|
Some(clip_mask),
|
||||||
);
|
);
|
||||||
|
|
||||||
if *border_width > 0.0 {
|
if *border_width > 0.0 {
|
||||||
|
|
@ -203,7 +248,7 @@ impl Backend {
|
||||||
..tiny_skia::Stroke::default()
|
..tiny_skia::Stroke::default()
|
||||||
},
|
},
|
||||||
transform,
|
transform,
|
||||||
clip_mask,
|
Some(clip_mask),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -216,10 +261,9 @@ impl Backend {
|
||||||
horizontal_alignment,
|
horizontal_alignment,
|
||||||
vertical_alignment,
|
vertical_alignment,
|
||||||
} => {
|
} => {
|
||||||
if !damage
|
if !clip_bounds.intersects(
|
||||||
.iter()
|
&((primitive.bounds() + translation) * scale_factor),
|
||||||
.any(|damage| damage.intersects(&primitive.bounds()))
|
) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,12 +276,14 @@ impl Backend {
|
||||||
*horizontal_alignment,
|
*horizontal_alignment,
|
||||||
*vertical_alignment,
|
*vertical_alignment,
|
||||||
pixels,
|
pixels,
|
||||||
clip_bounds.map(|_| clip_mask as &_),
|
Some(clip_mask),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[cfg(feature = "image")]
|
#[cfg(feature = "image")]
|
||||||
Primitive::Image { handle, bounds } => {
|
Primitive::Image { handle, bounds } => {
|
||||||
if !damage.iter().any(|damage| damage.intersects(bounds)) {
|
if !clip_bounds
|
||||||
|
.intersects(&((*bounds + translation) * scale_factor))
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,7 +298,7 @@ impl Backend {
|
||||||
*bounds,
|
*bounds,
|
||||||
pixels,
|
pixels,
|
||||||
transform,
|
transform,
|
||||||
clip_bounds.map(|_| clip_mask as &_),
|
Some(clip_mask),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[cfg(feature = "svg")]
|
#[cfg(feature = "svg")]
|
||||||
|
|
@ -275,6 +321,20 @@ impl Backend {
|
||||||
rule,
|
rule,
|
||||||
transform,
|
transform,
|
||||||
} => {
|
} => {
|
||||||
|
let bounds = path.bounds();
|
||||||
|
|
||||||
|
if !clip_bounds.intersects(
|
||||||
|
&((Rectangle {
|
||||||
|
x: bounds.x(),
|
||||||
|
y: bounds.y(),
|
||||||
|
width: bounds.width(),
|
||||||
|
height: bounds.height(),
|
||||||
|
} + translation)
|
||||||
|
* scale_factor),
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pixels.fill_path(
|
pixels.fill_path(
|
||||||
path,
|
path,
|
||||||
paint,
|
paint,
|
||||||
|
|
@ -282,7 +342,7 @@ impl Backend {
|
||||||
transform
|
transform
|
||||||
.post_translate(translation.x, translation.y)
|
.post_translate(translation.x, translation.y)
|
||||||
.post_scale(scale_factor, scale_factor),
|
.post_scale(scale_factor, scale_factor),
|
||||||
clip_bounds.map(|_| clip_mask as &_),
|
Some(clip_mask),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Primitive::Stroke {
|
Primitive::Stroke {
|
||||||
|
|
@ -291,6 +351,20 @@ impl Backend {
|
||||||
stroke,
|
stroke,
|
||||||
transform,
|
transform,
|
||||||
} => {
|
} => {
|
||||||
|
let bounds = path.bounds();
|
||||||
|
|
||||||
|
if !clip_bounds.intersects(
|
||||||
|
&((Rectangle {
|
||||||
|
x: bounds.x(),
|
||||||
|
y: bounds.y(),
|
||||||
|
width: bounds.width(),
|
||||||
|
height: bounds.height(),
|
||||||
|
} + translation)
|
||||||
|
* scale_factor),
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pixels.stroke_path(
|
pixels.stroke_path(
|
||||||
path,
|
path,
|
||||||
paint,
|
paint,
|
||||||
|
|
@ -298,7 +372,7 @@ impl Backend {
|
||||||
transform
|
transform
|
||||||
.post_translate(translation.x, translation.y)
|
.post_translate(translation.x, translation.y)
|
||||||
.post_scale(scale_factor, scale_factor),
|
.post_scale(scale_factor, scale_factor),
|
||||||
clip_bounds.map(|_| clip_mask as &_),
|
Some(clip_mask),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Primitive::Group { primitives } => {
|
Primitive::Group { primitives } => {
|
||||||
|
|
@ -310,7 +384,6 @@ impl Backend {
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
translation,
|
translation,
|
||||||
damage,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -325,7 +398,6 @@ impl Backend {
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
translation + *offset,
|
translation + *offset,
|
||||||
damage,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Primitive::Clip { bounds, content } => {
|
Primitive::Clip { bounds, content } => {
|
||||||
|
|
@ -339,22 +411,19 @@ impl Backend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
adjust_clip_mask(clip_mask, pixels, bounds);
|
if let Some(bounds) = clip_bounds.intersection(&bounds) {
|
||||||
|
|
||||||
self.draw_primitive(
|
|
||||||
content,
|
|
||||||
pixels,
|
|
||||||
clip_mask,
|
|
||||||
Some(bounds),
|
|
||||||
scale_factor,
|
|
||||||
translation,
|
|
||||||
damage,
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(bounds) = clip_bounds {
|
|
||||||
adjust_clip_mask(clip_mask, pixels, bounds);
|
adjust_clip_mask(clip_mask, pixels, bounds);
|
||||||
} else {
|
|
||||||
clip_mask.clear();
|
self.draw_primitive(
|
||||||
|
content,
|
||||||
|
pixels,
|
||||||
|
clip_mask,
|
||||||
|
bounds,
|
||||||
|
scale_factor,
|
||||||
|
translation,
|
||||||
|
);
|
||||||
|
|
||||||
|
adjust_clip_mask(clip_mask, pixels, clip_bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Primitive::Cache { content } => {
|
Primitive::Cache { content } => {
|
||||||
|
|
@ -365,7 +434,6 @@ impl Backend {
|
||||||
clip_bounds,
|
clip_bounds,
|
||||||
scale_factor,
|
scale_factor,
|
||||||
translation,
|
translation,
|
||||||
damage,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Primitive::SolidMesh { .. } | Primitive::GradientMesh { .. } => {
|
Primitive::SolidMesh { .. } | Primitive::GradientMesh { .. } => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue