Skip to content
This repository was archived by the owner on Jul 18, 2024. It is now read-only.

Commit 681e8bf

Browse files
authored
Merge pull request #29 from google/line-culling
Added line culling.
2 parents 5a8cd2d + 4e3afdc commit 681e8bf

File tree

8 files changed

+197
-139
lines changed

8 files changed

+197
-139
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## Unreleased
2+
3+
* Added line-culling to `SegmentBuffer` in #29

forma/src/composition/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#[cfg(test)]
16+
use std::cell::Ref;
1517
use std::{cell::RefCell, rc::Rc};
1618

1719
use rustc_hash::FxHashMap;
@@ -380,6 +382,19 @@ impl Composition {
380382
.retain(|id| geom_id_to_order.contains_key(&id));
381383
}
382384
}
385+
386+
#[cfg(test)]
387+
pub fn layers_for_segments(
388+
&self,
389+
) -> (
390+
&FxHashMap<Order, Layer>,
391+
Ref<FxHashMap<GeomId, Option<Order>>>,
392+
) {
393+
(
394+
&self.layers,
395+
Ref::map(self.shared_state.borrow(), |state| &state.geom_id_to_order),
396+
)
397+
}
383398
}
384399

385400
#[cfg(test)]

forma/src/cpu/painter/mod.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -792,16 +792,16 @@ pub fn painter_fill_at_bench(width: usize, height: usize, style: &Style) -> f32x
792792

793793
#[cfg(test)]
794794
mod tests {
795+
795796
use super::*;
796797

797798
use std::{collections::HashMap, iter};
798799

799800
use crate::{
800-
composition::InnerLayer,
801801
consts::cpu::{TILE_HEIGHT, TILE_WIDTH},
802802
cpu::{buffer::layout::LinearLayout, Rasterizer, RGBA},
803803
math::Point,
804-
GeomId, Order, SegmentBuffer,
804+
Composition, GeomId, Order, SegmentBuffer,
805805
};
806806

807807
const RED: Color = Color {
@@ -944,20 +944,25 @@ mod tests {
944944
points: &[(Point, Point)],
945945
same_layer: bool,
946946
) -> Vec<PixelSegment<TILE_WIDTH, TILE_HEIGHT>> {
947-
let mut builder = SegmentBuffer::default();
948-
let ids = iter::successors(Some(GeomId::default()), |id| Some(id.next()));
947+
let mut segment_buffer = SegmentBuffer::default();
948+
let mut composition = Composition::new();
949+
950+
if same_layer {
951+
composition.get_mut_or_insert_default(Order::new(0).unwrap());
949952

950-
for (&(p0, p1), id) in points.iter().zip(ids) {
951-
let id = if same_layer { GeomId::default() } else { id };
952-
builder.push(id, [p0, p1]);
953+
for &(p0, p1) in points.iter() {
954+
segment_buffer.push(GeomId::default(), [p0, p1]);
955+
}
956+
} else {
957+
for (id, &(p0, p1)) in points.iter().enumerate() {
958+
composition.get_mut_or_insert_default(Order::new(id as u32).unwrap());
959+
segment_buffer.push(GeomId::new(id as u64), [p0, p1]);
960+
}
953961
}
954962

955-
let lines = builder.fill_cpu_view(|id| {
956-
Some(InnerLayer {
957-
order: Some(Order::new(id.get() as u32).unwrap()),
958-
..Default::default()
959-
})
960-
});
963+
let (layers, geom_id_to_order) = composition.layers_for_segments();
964+
965+
let lines = segment_buffer.fill_cpu_view(usize::MAX, usize::MAX, layers, &geom_id_to_order);
961966

962967
let mut rasterizer = Rasterizer::default();
963968
rasterizer.rasterize(&lines);

forma/src/cpu/rasterizer.rs

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -169,22 +169,24 @@ mod tests {
169169
use super::*;
170170

171171
use crate::{
172-
composition::InnerLayer,
172+
composition::Composition,
173173
consts::cpu::{TILE_HEIGHT, TILE_WIDTH},
174174
math::Point,
175175
segment::{GeomId, SegmentBuffer},
176176
utils::Order,
177177
};
178178

179179
fn segments(p0: Point, p1: Point) -> Vec<PixelSegment<TILE_WIDTH, TILE_HEIGHT>> {
180-
let mut builder = SegmentBuffer::default();
181-
builder.push(GeomId::default(), [p0, p1]);
182-
let lines = builder.fill_cpu_view(|_| {
183-
Some(InnerLayer {
184-
order: Some(Order::new(0).unwrap()),
185-
..Default::default()
186-
})
187-
});
180+
let mut segment_buffer = SegmentBuffer::default();
181+
let mut composition = Composition::new();
182+
183+
composition.get_mut_or_insert_default(Order::new(0).unwrap());
184+
185+
segment_buffer.push(GeomId::default(), [p0, p1]);
186+
187+
let (layers, geom_id_to_order) = composition.layers_for_segments();
188+
189+
let lines = segment_buffer.fill_cpu_view(usize::MAX, usize::MAX, layers, &geom_id_to_order);
188190

189191
let mut rasterizer = Rasterizer::default();
190192
rasterizer.rasterize(&lines);
@@ -296,7 +298,7 @@ mod tests {
296298
#[test]
297299
fn area_cover_octant_5() {
298300
assert_eq!(
299-
areas_and_covers(&segments(Point::new(0.0, 0.0), Point::new(-3.0, -2.0))),
301+
areas_and_covers(&segments(Point::new(3.0, 2.0), Point::new(0.0, 0.0))),
300302
[
301303
(-(11 * 16), -11),
302304
(-(5 * 8), -5),
@@ -309,7 +311,7 @@ mod tests {
309311
#[test]
310312
fn area_cover_octant_6() {
311313
assert_eq!(
312-
areas_and_covers(&segments(Point::new(0.0, 0.0), Point::new(-2.0, -3.0))),
314+
areas_and_covers(&segments(Point::new(2.0, 3.0), Point::new(0.0, 0.0))),
313315
[
314316
(-(16 * 11), -16),
315317
(-(8 * 5 + 2 * (8 * 11)), -8),
@@ -322,7 +324,7 @@ mod tests {
322324
#[test]
323325
fn area_cover_octant_7() {
324326
assert_eq!(
325-
areas_and_covers(&segments(Point::new(0.0, 0.0), Point::new(2.0, -3.0))),
327+
areas_and_covers(&segments(Point::new(0.0, 3.0), Point::new(2.0, 0.0))),
326328
[
327329
(-(16 * 11 + 2 * (16 * 5)), -16),
328330
(-(8 * 5), -8),
@@ -335,7 +337,7 @@ mod tests {
335337
#[test]
336338
fn area_cover_octant_8() {
337339
assert_eq!(
338-
areas_and_covers(&segments(Point::new(0.0, 0.0), Point::new(3.0, -2.0))),
340+
areas_and_covers(&segments(Point::new(0.0, 2.0), Point::new(3.0, 0.0))),
339341
[
340342
(-(11 * 16), -11),
341343
(-(5 * 8 + 2 * (5 * 8)), -5),
@@ -388,23 +390,23 @@ mod tests {
388390
#[test]
389391
fn area_cover_axis_225() {
390392
assert_eq!(
391-
areas_and_covers(&segments(Point::new(0.0, 0.0), Point::new(-1.0, -1.0))),
393+
areas_and_covers(&segments(Point::new(1.0, 1.0), Point::new(0.0, 0.0))),
392394
[(-(16 * 16), -16)],
393395
);
394396
}
395397

396398
#[test]
397399
fn area_cover_axis_270() {
398400
assert_eq!(
399-
areas_and_covers(&segments(Point::new(0.0, 0.0), Point::new(0.0, -1.0))),
401+
areas_and_covers(&segments(Point::new(0.0, 1.0), Point::new(0.0, 0.0))),
400402
[(2 * -(16 * 16), -16)],
401403
);
402404
}
403405

404406
#[test]
405407
fn area_cover_axis_315() {
406408
assert_eq!(
407-
areas_and_covers(&segments(Point::new(0.0, 0.0), Point::new(-1.0, -1.0))),
409+
areas_and_covers(&segments(Point::new(0.0, 1.0), Point::new(1.0, 0.0))),
408410
[(-(16 * 16), -16)],
409411
);
410412
}
@@ -481,14 +483,14 @@ mod tests {
481483
fn tile_octant_5() {
482484
assert_eq!(
483485
tiles(&segments(
484-
Point::new(-(TILE_WIDTH as f32), -(TILE_HEIGHT as f32)),
485-
Point::new(-(TILE_WIDTH as f32) - 3.0, -(TILE_HEIGHT as f32) - 2.0),
486+
Point::new(-(TILE_WIDTH as f32), TILE_HEIGHT as f32),
487+
Point::new(-(TILE_WIDTH as f32) - 3.0, TILE_HEIGHT as f32 - 2.0),
486488
)),
487489
[
488-
(-1, -1, TILE_WIDTH as u8 - 1, TILE_HEIGHT as u8 - 1),
489-
(-1, -1, TILE_WIDTH as u8 - 2, TILE_HEIGHT as u8 - 1),
490-
(-1, -1, TILE_WIDTH as u8 - 2, TILE_HEIGHT as u8 - 2),
491-
(-1, -1, TILE_WIDTH as u8 - 3, TILE_HEIGHT as u8 - 2),
490+
(-1, 0, TILE_WIDTH as u8 - 1, TILE_HEIGHT as u8 - 1),
491+
(-1, 0, TILE_WIDTH as u8 - 2, TILE_HEIGHT as u8 - 1),
492+
(-1, 0, TILE_WIDTH as u8 - 2, TILE_HEIGHT as u8 - 2),
493+
(-1, 0, TILE_WIDTH as u8 - 3, TILE_HEIGHT as u8 - 2),
492494
],
493495
);
494496
}
@@ -497,14 +499,14 @@ mod tests {
497499
fn tile_octant_6() {
498500
assert_eq!(
499501
tiles(&segments(
500-
Point::new(-(TILE_WIDTH as f32), -(TILE_HEIGHT as f32)),
501-
Point::new(-(TILE_WIDTH as f32) - 2.0, -(TILE_HEIGHT as f32) - 3.0),
502+
Point::new(-(TILE_WIDTH as f32), TILE_HEIGHT as f32),
503+
Point::new(-(TILE_WIDTH as f32) - 2.0, TILE_HEIGHT as f32 - 3.0),
502504
)),
503505
[
504-
(-1, -1, TILE_WIDTH as u8 - 1, TILE_HEIGHT as u8 - 1),
505-
(-1, -1, TILE_WIDTH as u8 - 1, TILE_HEIGHT as u8 - 2),
506-
(-1, -1, TILE_WIDTH as u8 - 2, TILE_HEIGHT as u8 - 2),
507-
(-1, -1, TILE_WIDTH as u8 - 2, TILE_HEIGHT as u8 - 3),
506+
(-1, 0, TILE_WIDTH as u8 - 1, TILE_HEIGHT as u8 - 1),
507+
(-1, 0, TILE_WIDTH as u8 - 1, TILE_HEIGHT as u8 - 2),
508+
(-1, 0, TILE_WIDTH as u8 - 2, TILE_HEIGHT as u8 - 2),
509+
(-1, 0, TILE_WIDTH as u8 - 2, TILE_HEIGHT as u8 - 3),
508510
],
509511
);
510512
}
@@ -513,14 +515,14 @@ mod tests {
513515
fn tile_octant_7() {
514516
assert_eq!(
515517
tiles(&segments(
516-
Point::new(TILE_WIDTH as f32, -(TILE_HEIGHT as f32)),
517-
Point::new(TILE_WIDTH as f32 + 2.0, -(TILE_HEIGHT as f32) - 3.0),
518+
Point::new(TILE_WIDTH as f32, TILE_HEIGHT as f32),
519+
Point::new(TILE_WIDTH as f32 + 2.0, (TILE_HEIGHT as f32) - 3.0),
518520
)),
519521
[
520-
(1, -1, 0, TILE_HEIGHT as u8 - 1),
521-
(1, -1, 0, TILE_HEIGHT as u8 - 2),
522-
(1, -1, 1, TILE_HEIGHT as u8 - 2),
523-
(1, -1, 1, TILE_HEIGHT as u8 - 3),
522+
(1, 0, 0, TILE_HEIGHT as u8 - 1),
523+
(1, 0, 0, TILE_HEIGHT as u8 - 2),
524+
(1, 0, 1, TILE_HEIGHT as u8 - 2),
525+
(1, 0, 1, TILE_HEIGHT as u8 - 3),
524526
],
525527
);
526528
}
@@ -529,14 +531,14 @@ mod tests {
529531
fn tile_octant_8() {
530532
assert_eq!(
531533
tiles(&segments(
532-
Point::new(TILE_WIDTH as f32, -(TILE_HEIGHT as f32)),
533-
Point::new(TILE_WIDTH as f32 + 3.0, -(TILE_HEIGHT as f32) - 2.0),
534+
Point::new(TILE_WIDTH as f32, TILE_HEIGHT as f32),
535+
Point::new(TILE_WIDTH as f32 + 3.0, (TILE_HEIGHT as f32) - 2.0),
534536
)),
535537
[
536-
(1, -1, 0, TILE_HEIGHT as u8 - 1),
537-
(1, -1, 1, TILE_HEIGHT as u8 - 1),
538-
(1, -1, 1, TILE_HEIGHT as u8 - 2),
539-
(1, -1, 2, TILE_HEIGHT as u8 - 2),
538+
(1, 0, 0, TILE_HEIGHT as u8 - 1),
539+
(1, 0, 1, TILE_HEIGHT as u8 - 1),
540+
(1, 0, 1, TILE_HEIGHT as u8 - 2),
541+
(1, 0, 2, TILE_HEIGHT as u8 - 2),
540542
],
541543
);
542544
}

forma/src/cpu/renderer.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,26 +162,24 @@ impl Renderer {
162162
};
163163

164164
// `take()` sets the RefCell's content with `Default::default()` which is cheap for Option.
165-
let builder = segment_buffer
165+
let taken_buffer = segment_buffer
166166
.take()
167167
.expect("segment_buffer should not be None");
168168

169169
*segment_buffer = {
170-
let lines = {
170+
let segment_buffer_view = {
171171
duration!("gfx", "SegmentBuffer::fill_cpu_view");
172-
builder.fill_cpu_view(|id| {
173-
geom_id_to_order
174-
.get(&id)
175-
.copied()
176-
.flatten()
177-
.and_then(|order| context.layers.get(&order))
178-
.map(|layer| layer.inner.clone())
179-
})
172+
taken_buffer.fill_cpu_view(
173+
buffer.layout.width(),
174+
buffer.layout.height(),
175+
context.layers,
176+
geom_id_to_order,
177+
)
180178
};
181179

182180
{
183181
duration!("gfx", "Rasterizer::rasterize");
184-
rasterizer.rasterize(&lines);
182+
rasterizer.rasterize(&segment_buffer_view);
185183
}
186184
{
187185
duration!("gfx", "Rasterizer::sort");
@@ -213,7 +211,7 @@ impl Renderer {
213211
);
214212
}
215213

216-
Some(lines.recycle())
214+
Some(segment_buffer_view.recycle())
217215
};
218216

219217
if let Some(buffer_layer_cache) = &buffer.layer_cache {

0 commit comments

Comments
 (0)