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: 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: f32x16<S>,
25 ) -> f32x16<S> {
26 match self.compose {
27 Compose::SrcOver => SrcOver::compose(simd, src_c, bg_c, alpha_mask),
28 Compose::Clear => Clear::compose(simd, src_c, bg_c, alpha_mask),
29 Compose::Copy => Copy::compose(simd, src_c, bg_c, alpha_mask),
30 Compose::DestOver => DestOver::compose(simd, src_c, bg_c, alpha_mask),
31 Compose::Dest => Dest::compose(simd, src_c, bg_c, alpha_mask),
32 Compose::SrcIn => SrcIn::compose(simd, src_c, bg_c, alpha_mask),
33 Compose::DestIn => DestIn::compose(simd, src_c, bg_c, alpha_mask),
34 Compose::SrcOut => SrcOut::compose(simd, src_c, bg_c, alpha_mask),
35 Compose::DestOut => DestOut::compose(simd, src_c, bg_c, alpha_mask),
36 Compose::SrcAtop => SrcAtop::compose(simd, src_c, bg_c, alpha_mask),
37 Compose::DestAtop => DestAtop::compose(simd, src_c, bg_c, alpha_mask),
38 Compose::Xor => Xor::compose(simd, src_c, bg_c, alpha_mask),
39 Compose::Plus => Plus::compose(simd, src_c, bg_c, alpha_mask),
40 Compose::PlusLighter => Plus::compose(simd, src_c, bg_c, alpha_mask),
42 }
43 }
44}
45
46macro_rules! compose {
47 ($name:ident, $fa:expr, $fb:expr, $sat:expr) => {
48 struct $name;
49
50 impl $name {
51 fn compose<S: Simd>(
52 simd: S,
53 src_c: f32x16<S>,
54 bg_c: f32x16<S>,
55 mask: f32x16<S>,
56 ) -> f32x16<S> {
57 let al_b = bg_c.splat_4th();
58 let al_s = src_c.splat_4th() * mask;
59
60 let fa = $fa(simd, al_s, al_b);
61 let fb = $fb(simd, al_s, al_b);
62
63 let src_c = src_c * mask;
64
65 if $sat {
66 (src_c * fa + fb * bg_c)
67 .min(f32x16::splat(simd, 1.0))
68 .max(f32x16::splat(simd, 0.0))
69 } else {
70 src_c * fa + fb * bg_c
71 }
72 }
73 }
74 };
75}
76
77compose!(
78 Clear,
79 |simd, _, _| f32x16::splat(simd, 0.0),
80 |simd, _, _| f32x16::splat(simd, 0.0),
81 false
82);
83compose!(
84 Copy,
85 |simd, _, _| f32x16::splat(simd, 1.0),
86 |simd, _, _| f32x16::splat(simd, 0.0),
87 false
88);
89compose!(
90 SrcOver,
91 |simd, _, _| f32x16::splat(simd, 1.0),
92 |_, al_s: f32x16<S>, _| 1.0 - al_s,
93 false
94);
95compose!(
96 DestOver,
97 |_, _, al_b: f32x16<S>| 1.0 - al_b,
98 |simd, _, _| f32x16::splat(simd, 1.0),
99 false
100);
101compose!(
102 Dest,
103 |simd, _, _| f32x16::splat(simd, 0.0),
104 |simd, _, _| f32x16::splat(simd, 1.0),
105 false
106);
107compose!(
108 Xor,
109 |_, _, al_b: f32x16<S>| 1.0 - al_b,
110 |_, al_s: f32x16<S>, _| 1.0 - al_s,
111 false
112);
113compose!(
114 SrcIn,
115 |_, _, al_b: f32x16<S>| al_b,
116 |simd, _, _| f32x16::splat(simd, 0.0),
117 false
118);
119compose!(
120 DestIn,
121 |simd, _, _| f32x16::splat(simd, 0.0),
122 |_, al_s: f32x16<S>, _| al_s,
123 false
124);
125compose!(
126 SrcOut,
127 |_, _, al_b: f32x16<S>| 1.0 - al_b,
128 |simd, _, _| f32x16::splat(simd, 0.0),
129 false
130);
131compose!(
132 DestOut,
133 |simd, _, _| f32x16::splat(simd, 0.0),
134 |_, al_s: f32x16<S>, _| 1.0 - al_s,
135 false
136);
137compose!(
138 SrcAtop,
139 |_, _, al_b: f32x16<S>| al_b,
140 |_, al_s: f32x16<S>, _| 1.0 - al_s,
141 false
142);
143compose!(
144 DestAtop,
145 |_, _, al_b: f32x16<S>| 1.0 - al_b,
146 |_, al_s: f32x16<S>, _| al_s,
147 false
148);
149compose!(
150 Plus,
151 |simd, _, _| f32x16::splat(simd, 1.0),
152 |simd, _, _| f32x16::splat(simd, 1.0),
153 true
154);