1use crate::fine::Splat4thExt;
5use crate::peniko::{BlendMode, Compose};
6use vello_common::fearless_simd::*;
7
8pub(crate) trait ComposeExt {
9 fn compose<S: Simd>(
10 &self,
11 simd: S,
12 src_c: f32x16<S>,
13 bg_c: f32x16<S>,
14 alpha_mask: Option<f32x16<S>>,
15 ) -> f32x16<S>;
16}
17
18impl ComposeExt for BlendMode {
19 fn compose<S: Simd>(
20 &self,
21 simd: S,
22 src_c: f32x16<S>,
23 bg_c: f32x16<S>,
24 alpha_mask: Option<f32x16<S>>,
25 ) -> f32x16<S> {
26 let mut res = match self.compose {
44 Compose::SrcOver => SrcOver::compose(simd, src_c, bg_c),
45 Compose::Clear => Clear::compose(simd, src_c, bg_c),
46 Compose::Copy => Copy::compose(simd, src_c, bg_c),
47 Compose::DestOver => DestOver::compose(simd, src_c, bg_c),
48 Compose::Dest => Dest::compose(simd, src_c, bg_c),
49 Compose::SrcIn => SrcIn::compose(simd, src_c, bg_c),
50 Compose::DestIn => DestIn::compose(simd, src_c, bg_c),
51 Compose::SrcOut => SrcOut::compose(simd, src_c, bg_c),
52 Compose::DestOut => DestOut::compose(simd, src_c, bg_c),
53 Compose::SrcAtop => SrcAtop::compose(simd, src_c, bg_c),
54 Compose::DestAtop => DestAtop::compose(simd, src_c, bg_c),
55 Compose::Xor => Xor::compose(simd, src_c, bg_c),
56 Compose::Plus => Plus::compose(simd, src_c, bg_c),
57 Compose::PlusLighter => Plus::compose(simd, src_c, bg_c),
59 };
60
61 if let Some(alpha_mask) = alpha_mask {
62 let alpha_mask_inv = 1.0 - alpha_mask;
63 res = alpha_mask * res + alpha_mask_inv * bg_c;
64 }
65
66 res
67 }
68}
69
70macro_rules! compose {
71 ($name:ident, $fa:expr, $fb:expr, $sat:expr) => {
72 struct $name;
73
74 impl $name {
75 fn compose<S: Simd>(simd: S, src_c: f32x16<S>, bg_c: f32x16<S>) -> f32x16<S> {
76 let al_b = bg_c.splat_4th();
77 let al_s = src_c.splat_4th();
78
79 let fa = $fa(simd, al_s, al_b);
80 let fb = $fb(simd, al_s, al_b);
81
82 if $sat {
83 (src_c * fa + fb * bg_c)
84 .min(f32x16::splat(simd, 1.0))
85 .max(f32x16::splat(simd, 0.0))
86 } else {
87 src_c * fa + fb * bg_c
88 }
89 }
90 }
91 };
92}
93
94compose!(
95 Clear,
96 |simd, _, _| f32x16::splat(simd, 0.0),
97 |simd, _, _| f32x16::splat(simd, 0.0),
98 false
99);
100compose!(
101 Copy,
102 |simd, _, _| f32x16::splat(simd, 1.0),
103 |simd, _, _| f32x16::splat(simd, 0.0),
104 false
105);
106compose!(
107 SrcOver,
108 |simd, _, _| f32x16::splat(simd, 1.0),
109 |_, al_s: f32x16<S>, _| 1.0 - al_s,
110 false
111);
112compose!(
113 DestOver,
114 |_, _, al_b: f32x16<S>| 1.0 - al_b,
115 |simd, _, _| f32x16::splat(simd, 1.0),
116 false
117);
118compose!(
119 Dest,
120 |simd, _, _| f32x16::splat(simd, 0.0),
121 |simd, _, _| f32x16::splat(simd, 1.0),
122 false
123);
124compose!(
125 Xor,
126 |_, _, al_b: f32x16<S>| 1.0 - al_b,
127 |_, al_s: f32x16<S>, _| 1.0 - al_s,
128 false
129);
130compose!(
131 SrcIn,
132 |_, _, al_b: f32x16<S>| al_b,
133 |simd, _, _| f32x16::splat(simd, 0.0),
134 false
135);
136compose!(
137 DestIn,
138 |simd, _, _| f32x16::splat(simd, 0.0),
139 |_, al_s: f32x16<S>, _| al_s,
140 false
141);
142compose!(
143 SrcOut,
144 |_, _, al_b: f32x16<S>| 1.0 - al_b,
145 |simd, _, _| f32x16::splat(simd, 0.0),
146 false
147);
148compose!(
149 DestOut,
150 |simd, _, _| f32x16::splat(simd, 0.0),
151 |_, al_s: f32x16<S>, _| 1.0 - al_s,
152 false
153);
154compose!(
155 SrcAtop,
156 |_, _, al_b: f32x16<S>| al_b,
157 |_, al_s: f32x16<S>, _| 1.0 - al_s,
158 false
159);
160compose!(
161 DestAtop,
162 |_, _, al_b: f32x16<S>| 1.0 - al_b,
163 |_, al_s: f32x16<S>, _| al_s,
164 false
165);
166compose!(
167 Plus,
168 |simd, _, _| f32x16::splat(simd, 1.0),
169 |simd, _, _| f32x16::splat(simd, 1.0),
170 true
171);