surpass/painter/layer_workbench/passes/
skip_fully_covered_layers.rs
1use std::ops::ControlFlow;
6
7use crate::painter::layer_workbench::passes::PassesSharedState;
8use crate::painter::layer_workbench::{Context, LayerWorkbenchState, OptimizerTileWriteOp};
9use crate::painter::{BlendMode, Color, Fill, Func, LayerProps, Style};
10
11pub fn skip_fully_covered_layers_pass<'w, 'c, P: LayerProps>(
12 workbench: &'w mut LayerWorkbenchState,
13 state: &'w mut PassesSharedState,
14 context: &'c Context<'_, P>,
15) -> ControlFlow<OptimizerTileWriteOp> {
16 #[derive(Debug)]
17 enum InterestingCover {
18 Opaque(Color),
19 Incomplete,
20 }
21
22 let mut first_interesting_cover = None;
23 let mut visible_layers_are_unchanged = !state.layers_were_removed;
26 for (i, &id) in workbench.ids.iter_masked().rev() {
27 let props = context.props.get(id);
28
29 if !context.props.is_unchanged(id) {
30 visible_layers_are_unchanged = false;
31 }
32
33 let is_clipped = || {
34 matches!(props.func, Func::Draw(Style { is_clipped: true, .. }))
35 && !state.skip_clipping.contains(&id)
36 };
37
38 if is_clipped() || !workbench.layer_is_full(context, id, props.fill_rule) {
39 if first_interesting_cover.is_none() {
40 first_interesting_cover = Some(InterestingCover::Incomplete);
41 }
44 } else if let Func::Draw(Style {
45 fill: Fill::Solid(color),
46 blend_mode: BlendMode::Over,
47 ..
48 }) = props.func
49 {
50 if color.a == 1.0 {
51 if first_interesting_cover.is_none() {
52 first_interesting_cover = Some(InterestingCover::Opaque(color));
53 }
54
55 workbench.ids.skip_until(i);
56
57 break;
58 }
59 }
60 }
61
62 let (i, bottom_color) = match first_interesting_cover {
63 Some(InterestingCover::Opaque(color)) => {
65 if visible_layers_are_unchanged {
67 return ControlFlow::Break(OptimizerTileWriteOp::None);
68 }
69
70 (1, color)
71 }
72 None => (0, context.clear_color),
74 Some(InterestingCover::Incomplete) => return ControlFlow::Continue(()),
76 };
77
78 let color = workbench.ids.iter_masked().skip(i).try_fold(bottom_color, |dst, (_, &id)| {
79 match context.props.get(id).func {
80 Func::Draw(Style { fill: Fill::Solid(color), blend_mode, .. }) => {
81 Some(blend_mode.blend(dst, color))
82 }
83 _ => None,
85 }
86 });
87
88 match color {
89 Some(color) => ControlFlow::Break(OptimizerTileWriteOp::Solid(color)),
90 None => ControlFlow::Continue(()),
91 }
92}