Changeset View
Changeset View
Standalone View
Standalone View
libs/pigment/compositeops/KoOptimizedCompositeOpAlphaDarken128.h
Show All 23 Lines | |||||
24 | #include "KoCompositeOpRegistry.h" | 24 | #include "KoCompositeOpRegistry.h" | ||
25 | #include "KoStreamedMath.h" | 25 | #include "KoStreamedMath.h" | ||
26 | 26 | | |||
27 | template<typename channels_type, typename pixel_type> | 27 | template<typename channels_type, typename pixel_type> | ||
28 | struct AlphaDarkenCompositor128 { | 28 | struct AlphaDarkenCompositor128 { | ||
29 | struct OptionalParams { | 29 | struct OptionalParams { | ||
30 | OptionalParams(const KoCompositeOp::ParameterInfo& params) | 30 | OptionalParams(const KoCompositeOp::ParameterInfo& params) | ||
31 | : flow(params.flow) | 31 | : flow(params.flow) | ||
32 | , averageOpacity(*params.lastOpacity * params.flow) | 32 | , averageOpacity(*params.lastOpacity) | ||
33 | , premultipliedOpacity(params.opacity * params.flow) | | |||
34 | { | 33 | { | ||
35 | } | 34 | } | ||
36 | float flow; | 35 | float flow; | ||
37 | float averageOpacity; | 36 | float averageOpacity; | ||
38 | float premultipliedOpacity; | | |||
39 | }; | 37 | }; | ||
40 | 38 | | |||
41 | struct Pixel { | 39 | struct Pixel { | ||
42 | channels_type red; | 40 | channels_type red; | ||
43 | channels_type green; | 41 | channels_type green; | ||
44 | channels_type blue; | 42 | channels_type blue; | ||
45 | channels_type alpha; | 43 | channels_type alpha; | ||
46 | }; | 44 | }; | ||
Show All 31 Lines | 75 | if (haveMask) { | |||
78 | const Vc::float_v uint8Rec1((float)1.0 / 255.0); | 76 | const Vc::float_v uint8Rec1((float)1.0 / 255.0); | ||
79 | Vc::float_v mask_vec = KoStreamedMath<_impl>::fetch_mask_8(mask); | 77 | Vc::float_v mask_vec = KoStreamedMath<_impl>::fetch_mask_8(mask); | ||
80 | msk_norm_alpha = mask_vec * uint8Rec1 * src_alpha; | 78 | msk_norm_alpha = mask_vec * uint8Rec1 * src_alpha; | ||
81 | } | 79 | } | ||
82 | else { | 80 | else { | ||
83 | msk_norm_alpha = src_alpha; | 81 | msk_norm_alpha = src_alpha; | ||
84 | } | 82 | } | ||
85 | 83 | | |||
86 | // we don't use directly passed value | 84 | Vc::float_v opacity_vec(opacity); | ||
87 | Q_UNUSED(opacity); | | |||
88 | | ||||
89 | // instead we should use opacity premultiplied by flow | | |||
90 | opacity = oparams.premultipliedOpacity; | | |||
91 | Vc::float_v opacity_vec(oparams.premultipliedOpacity); | | |||
92 | 85 | | |||
93 | src_alpha = msk_norm_alpha * opacity_vec; | 86 | src_alpha = msk_norm_alpha * opacity_vec; | ||
94 | 87 | | |||
95 | const Vc::float_v zeroValue(KoColorSpaceMathsTraits<channels_type>::zeroValue); | 88 | const Vc::float_v zeroValue(KoColorSpaceMathsTraits<channels_type>::zeroValue); | ||
96 | 89 | | |||
97 | Vc::float_v dst_c1; | 90 | Vc::float_v dst_c1; | ||
98 | Vc::float_v dst_c2; | 91 | Vc::float_v dst_c2; | ||
99 | Vc::float_v dst_c3; | 92 | Vc::float_v dst_c3; | ||
Show All 37 Lines | 129 | else { | |||
137 | Vc::float_m fullFlowAlpha_mask = opacity_vec > dst_alpha; | 130 | Vc::float_m fullFlowAlpha_mask = opacity_vec > dst_alpha; | ||
138 | fullFlowAlpha(fullFlowAlpha_mask) = (opacity_vec - dst_alpha) * msk_norm_alpha + dst_alpha; | 131 | fullFlowAlpha(fullFlowAlpha_mask) = (opacity_vec - dst_alpha) * msk_norm_alpha + dst_alpha; | ||
139 | } | 132 | } | ||
140 | 133 | | |||
141 | if (oparams.flow == 1.0) { | 134 | if (oparams.flow == 1.0) { | ||
142 | dst_alpha = fullFlowAlpha; | 135 | dst_alpha = fullFlowAlpha; | ||
143 | } | 136 | } | ||
144 | else { | 137 | else { | ||
145 | Vc::float_v zeroFlowAlpha = src_alpha + dst_alpha - src_alpha * dst_alpha; | 138 | Vc::float_v zeroFlowAlpha = dst_alpha; | ||
146 | Vc::float_v flow_norm_vec(oparams.flow); | 139 | Vc::float_v flow_norm_vec(oparams.flow); | ||
147 | dst_alpha = (fullFlowAlpha - zeroFlowAlpha) * flow_norm_vec + zeroFlowAlpha; | 140 | dst_alpha = (fullFlowAlpha - zeroFlowAlpha) * flow_norm_vec + zeroFlowAlpha; | ||
148 | } | 141 | } | ||
149 | dataDest[indexes] = tie(dst_c1, dst_c2, dst_c3, dst_alpha); | 142 | dataDest[indexes] = tie(dst_c1, dst_c2, dst_c3, dst_alpha); | ||
150 | } | 143 | } | ||
151 | 144 | | |||
152 | /** | 145 | /** | ||
153 | * Composes one pixel of the source into the destination | 146 | * Composes one pixel of the source into the destination | ||
154 | */ | 147 | */ | ||
155 | template <bool haveMask, Vc::Implementation _impl> | 148 | template <bool haveMask, Vc::Implementation _impl> | ||
156 | static ALWAYS_INLINE void compositeOnePixelScalar(const quint8 *s, quint8 *d, const quint8 *mask, float opacity, const OptionalParams &oparams) | 149 | static ALWAYS_INLINE void compositeOnePixelScalar(const quint8 *s, quint8 *d, const quint8 *mask, float opacity, const OptionalParams &oparams) | ||
157 | { | 150 | { | ||
158 | using namespace Arithmetic; | 151 | using namespace Arithmetic; | ||
159 | const qint32 alpha_pos = 3; | 152 | const qint32 alpha_pos = 3; | ||
160 | 153 | | |||
161 | const channels_type *src = reinterpret_cast<const channels_type*>(s); | 154 | const channels_type *src = reinterpret_cast<const channels_type*>(s); | ||
162 | channels_type *dst = reinterpret_cast<channels_type*>(d); | 155 | channels_type *dst = reinterpret_cast<channels_type*>(d); | ||
163 | 156 | | |||
164 | float dstAlphaNorm = dst[alpha_pos]; | 157 | float dstAlphaNorm = dst[alpha_pos]; | ||
165 | 158 | | |||
166 | const float uint8Rec1 = 1.0 / 255.0; | 159 | const float uint8Rec1 = 1.0 / 255.0; | ||
167 | float mskAlphaNorm = haveMask ? float(*mask) * uint8Rec1 * src[alpha_pos] : src[alpha_pos]; | 160 | float mskAlphaNorm = haveMask ? float(*mask) * uint8Rec1 * src[alpha_pos] : src[alpha_pos]; | ||
168 | 161 | | |||
169 | Q_UNUSED(opacity); | | |||
170 | opacity = oparams.premultipliedOpacity; | | |||
171 | | ||||
172 | float srcAlphaNorm = mskAlphaNorm * opacity; | 162 | float srcAlphaNorm = mskAlphaNorm * opacity; | ||
173 | 163 | | |||
174 | if (dstAlphaNorm != 0) { | 164 | if (dstAlphaNorm != 0) { | ||
175 | dst[0] = lerp(dst[0], src[0], srcAlphaNorm); | 165 | dst[0] = lerp(dst[0], src[0], srcAlphaNorm); | ||
176 | dst[1] = lerp(dst[1], src[1], srcAlphaNorm); | 166 | dst[1] = lerp(dst[1], src[1], srcAlphaNorm); | ||
177 | dst[2] = lerp(dst[2], src[2], srcAlphaNorm); | 167 | dst[2] = lerp(dst[2], src[2], srcAlphaNorm); | ||
178 | } else { | 168 | } else { | ||
179 | const pixel_type *s = reinterpret_cast<const pixel_type*>(src); | 169 | const pixel_type *s = reinterpret_cast<const pixel_type*>(src); | ||
Show All 10 Lines | 179 | if (averageOpacity > opacity) { | |||
190 | fullFlowAlpha = averageOpacity > dstAlphaNorm ? lerp(srcAlphaNorm, averageOpacity, dstAlphaNorm / averageOpacity) : dstAlphaNorm; | 180 | fullFlowAlpha = averageOpacity > dstAlphaNorm ? lerp(srcAlphaNorm, averageOpacity, dstAlphaNorm / averageOpacity) : dstAlphaNorm; | ||
191 | } else { | 181 | } else { | ||
192 | fullFlowAlpha = opacity > dstAlphaNorm ? lerp(dstAlphaNorm, opacity, mskAlphaNorm) : dstAlphaNorm; | 182 | fullFlowAlpha = opacity > dstAlphaNorm ? lerp(dstAlphaNorm, opacity, mskAlphaNorm) : dstAlphaNorm; | ||
193 | } | 183 | } | ||
194 | 184 | | |||
195 | if (flow == 1.0) { | 185 | if (flow == 1.0) { | ||
196 | dst[alpha_pos] = fullFlowAlpha; | 186 | dst[alpha_pos] = fullFlowAlpha; | ||
197 | } else { | 187 | } else { | ||
198 | float zeroFlowAlpha = unionShapeOpacity(srcAlphaNorm, dstAlphaNorm); | 188 | float zeroFlowAlpha = dstAlphaNorm; | ||
199 | dst[alpha_pos] = lerp(zeroFlowAlpha, fullFlowAlpha, flow); | 189 | dst[alpha_pos] = lerp(zeroFlowAlpha, fullFlowAlpha, flow); | ||
200 | } | 190 | } | ||
201 | } | 191 | } | ||
202 | }; | 192 | }; | ||
203 | 193 | | |||
204 | /** | 194 | /** | ||
205 | * An optimized version of a composite op for the use in 16 byte | 195 | * An optimized version of a composite op for the use in 16 byte | ||
206 | * colorspaces with alpha channel placed at the last byte of | 196 | * colorspaces with alpha channel placed at the last byte of | ||
Show All 22 Lines |