mirror of
https://github.com/italicsjenga/vello.git
synced 2025-01-09 12:21:31 +11:00
Oops, forgot to commit mmark.rs
This commit is contained in:
parent
6fc1ed8e13
commit
a20c9e1592
191
examples/scenes/src/mmark.rs
Normal file
191
examples/scenes/src/mmark.rs
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
//! A benchmark based on MotionMark 1.2's path benchmark.
|
||||||
|
|
||||||
|
use rand::{seq::SliceRandom, Rng};
|
||||||
|
use vello::peniko::Color;
|
||||||
|
use vello::{
|
||||||
|
kurbo::{Affine, BezPath, CubicBez, Line, ParamCurve, PathSeg, Point, QuadBez},
|
||||||
|
peniko::Stroke,
|
||||||
|
SceneBuilder,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{SceneParams, TestScene};
|
||||||
|
|
||||||
|
const WIDTH: usize = 1600;
|
||||||
|
const HEIGHT: usize = 900;
|
||||||
|
|
||||||
|
const GRID_WIDTH: i64 = 80;
|
||||||
|
const GRID_HEIGHT: i64 = 40;
|
||||||
|
|
||||||
|
pub struct MMark {
|
||||||
|
elements: Vec<Element>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Element {
|
||||||
|
seg: PathSeg,
|
||||||
|
color: Color,
|
||||||
|
width: f64,
|
||||||
|
is_split: bool,
|
||||||
|
grid_point: GridPoint,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct GridPoint((i64, i64));
|
||||||
|
|
||||||
|
impl MMark {
|
||||||
|
pub fn new(n: usize) -> MMark {
|
||||||
|
let mut result = MMark { elements: vec![] };
|
||||||
|
result.resize(n);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resize(&mut self, n: usize) {
|
||||||
|
let old_n = self.elements.len();
|
||||||
|
if n < old_n {
|
||||||
|
self.elements.truncate(n)
|
||||||
|
} else if n > old_n {
|
||||||
|
let mut last = self
|
||||||
|
.elements
|
||||||
|
.last()
|
||||||
|
.map(|e| e.grid_point)
|
||||||
|
.unwrap_or(GridPoint((GRID_WIDTH / 2, GRID_HEIGHT / 2)));
|
||||||
|
self.elements.extend((old_n..n).map(|_| {
|
||||||
|
let element = Element::new_rand(last);
|
||||||
|
last = element.grid_point;
|
||||||
|
element
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestScene for MMark {
|
||||||
|
fn render(&mut self, sb: &mut SceneBuilder, params: &mut SceneParams) {
|
||||||
|
let c = params.complexity;
|
||||||
|
let n = if c < 10 {
|
||||||
|
(c + 1) * 1000
|
||||||
|
} else {
|
||||||
|
((c - 8) * 10000).min(120_000)
|
||||||
|
};
|
||||||
|
self.resize(n);
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let mut path = BezPath::new();
|
||||||
|
let len = self.elements.len();
|
||||||
|
for (i, element) in self.elements.iter_mut().enumerate() {
|
||||||
|
if path.is_empty() {
|
||||||
|
path.move_to(element.seg.start());
|
||||||
|
}
|
||||||
|
match element.seg {
|
||||||
|
PathSeg::Line(l) => path.line_to(l.p1),
|
||||||
|
PathSeg::Quad(q) => path.quad_to(q.p1, q.p2),
|
||||||
|
PathSeg::Cubic(c) => path.curve_to(c.p1, c.p2, c.p3),
|
||||||
|
}
|
||||||
|
if element.is_split || i == len {
|
||||||
|
// This gets color and width from the last element, original
|
||||||
|
// gets it from the first, but this should not matter.
|
||||||
|
sb.stroke(
|
||||||
|
&Stroke::new(element.width as f32),
|
||||||
|
Affine::IDENTITY,
|
||||||
|
element.color,
|
||||||
|
None,
|
||||||
|
&path,
|
||||||
|
);
|
||||||
|
path.truncate(0); // Should have clear method, to avoid allocations.
|
||||||
|
}
|
||||||
|
if rng.gen::<f32>() > 0.995 {
|
||||||
|
element.is_split ^= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let label = format!("mmark test: {} path elements (up/down to adjust)", n);
|
||||||
|
params.text.add(
|
||||||
|
sb,
|
||||||
|
None,
|
||||||
|
40.0,
|
||||||
|
None,
|
||||||
|
Affine::translate((100.0, 1100.0)),
|
||||||
|
&label,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const COLORS: &[Color] = &[
|
||||||
|
Color::rgb8(0x10, 0x10, 0x10),
|
||||||
|
Color::rgb8(0x80, 0x80, 0x80),
|
||||||
|
Color::rgb8(0xc0, 0xc0, 0xc0),
|
||||||
|
Color::rgb8(0x10, 0x10, 0x10),
|
||||||
|
Color::rgb8(0x80, 0x80, 0x80),
|
||||||
|
Color::rgb8(0xc0, 0xc0, 0xc0),
|
||||||
|
Color::rgb8(0xe0, 0x10, 0x40),
|
||||||
|
];
|
||||||
|
|
||||||
|
impl Element {
|
||||||
|
fn new_rand(last: GridPoint) -> Element {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let seg_type = rng.gen_range(0..4);
|
||||||
|
let next = GridPoint::random_point(last);
|
||||||
|
let (grid_point, seg) = if seg_type < 2 {
|
||||||
|
(
|
||||||
|
next,
|
||||||
|
PathSeg::Line(Line::new(last.coordinate(), next.coordinate())),
|
||||||
|
)
|
||||||
|
} else if seg_type < 3 {
|
||||||
|
let p2 = GridPoint::random_point(next);
|
||||||
|
(
|
||||||
|
p2,
|
||||||
|
PathSeg::Quad(QuadBez::new(
|
||||||
|
last.coordinate(),
|
||||||
|
next.coordinate(),
|
||||||
|
p2.coordinate(),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
let p2 = GridPoint::random_point(next);
|
||||||
|
let p3 = GridPoint::random_point(next);
|
||||||
|
(
|
||||||
|
p3,
|
||||||
|
PathSeg::Cubic(CubicBez::new(
|
||||||
|
last.coordinate(),
|
||||||
|
next.coordinate(),
|
||||||
|
p2.coordinate(),
|
||||||
|
p3.coordinate(),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let color = COLORS.choose(&mut rng).unwrap().clone();
|
||||||
|
let width = rng.gen::<f64>().powi(5) * 20.0 + 1.0;
|
||||||
|
let is_split = rng.gen();
|
||||||
|
Element {
|
||||||
|
seg,
|
||||||
|
color,
|
||||||
|
width,
|
||||||
|
is_split,
|
||||||
|
grid_point,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const OFFSETS: &[(i64, i64)] = &[(-4, 0), (2, 0), (1, -2), (1, 2)];
|
||||||
|
|
||||||
|
impl GridPoint {
|
||||||
|
fn random_point(last: GridPoint) -> GridPoint {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
|
let offset = OFFSETS.choose(&mut rng).unwrap();
|
||||||
|
let mut x = last.0 .0 + offset.0;
|
||||||
|
if x < 0 || x > GRID_WIDTH {
|
||||||
|
x -= offset.0 * 2;
|
||||||
|
}
|
||||||
|
let mut y = last.0 .1 + offset.1;
|
||||||
|
if y < 0 || y > GRID_HEIGHT {
|
||||||
|
y -= offset.1 * 2;
|
||||||
|
}
|
||||||
|
GridPoint((x, y))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn coordinate(&self) -> Point {
|
||||||
|
let scale_x = WIDTH as f64 / ((GRID_WIDTH + 1) as f64);
|
||||||
|
let scale_y = HEIGHT as f64 / ((GRID_HEIGHT + 1) as f64);
|
||||||
|
Point::new(
|
||||||
|
(self.0 .0 as f64 + 0.5) * scale_x,
|
||||||
|
100.0 + (self.0 .1 as f64 + 0.5) * scale_y,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue