Krita Source Code Documentation
Loading...
Searching...
No Matches
KoStreamedMath< _impl > Struct Template Reference

#include <KoStreamedMath.h>

Public Types

using float_v = xsimd::batch<float, _impl>
 
using int_v = xsimd::batch<int, _impl>
 
using uint_v = xsimd::batch<unsigned int, _impl>
 

Static Public Member Functions

template<bool aligned>
static float_v fetch_alpha_32 (const void *data)
 
template<bool aligned>
static void fetch_colors_32 (const void *data, float_v &c1, float_v &c2, float_v &c3)
 
static float_v fetch_mask_8 (const quint8 *data)
 
template<bool useMask, bool useFlow, class Compositor , int pixelSize>
static void genericComposite (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite128 (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite128_novector (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite32 (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite32_novector (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite64 (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor >
static void genericComposite64_novector (const KoCompositeOp::ParameterInfo &params)
 
template<bool useMask, bool useFlow, class Compositor , int pixelSize>
static void genericComposite_novector (const KoCompositeOp::ParameterInfo &params)
 
static quint8 lerp_mixed_u8_float (quint8 a, quint8 b, float alpha)
 
static quint8 round_float_to_u8 (float x)
 
static void write_channels_32 (void *data, const float_v alpha, const float_v c1, const float_v c2, const float_v c3)
 
static void write_channels_32_unaligned (void *data, const float_v alpha, const float_v c1, const float_v c2, const float_v c3)
 

Detailed Description

template<typename _impl>
struct KoStreamedMath< _impl >

Definition at line 152 of file KoStreamedMath.h.

Member Typedef Documentation

◆ float_v

template<typename _impl >
using KoStreamedMath< _impl >::float_v = xsimd::batch<float, _impl>

Definition at line 155 of file KoStreamedMath.h.

◆ int_v

template<typename _impl >
using KoStreamedMath< _impl >::int_v = xsimd::batch<int, _impl>

Definition at line 153 of file KoStreamedMath.h.

◆ uint_v

template<typename _impl >
using KoStreamedMath< _impl >::uint_v = xsimd::batch<unsigned int, _impl>

Definition at line 154 of file KoStreamedMath.h.

Member Function Documentation

◆ fetch_alpha_32()

template<typename _impl >
template<bool aligned>
static float_v KoStreamedMath< _impl >::fetch_alpha_32 ( const void * data)
inlinestatic

Get an alpha values from float_v::size pixels 32-bit each (4 channels, 8 bit per channel). The alpha value is considered to be stored in the most significant byte of the pixel

aligned controls whether the data is fetched using aligned instruction or not. 1) Fetching aligned data with unaligned instruction degrades performance. 2) Fetching unaligned data with aligned instruction causes #GP (General Protection Exception)

Definition at line 254 of file KoStreamedMath.h.

255 {
256 using U = typename std::conditional<aligned, xsimd::aligned_mode, xsimd::unaligned_mode>::type;
257 const auto data_i = uint_v::load(static_cast<const typename uint_v::value_type *>(data), U{});
258 return xsimd::to_float(xsimd::bitwise_cast_compat<int>(data_i >> 24));
259 }

◆ fetch_colors_32()

template<typename _impl >
template<bool aligned>
static void KoStreamedMath< _impl >::fetch_colors_32 ( const void * data,
float_v & c1,
float_v & c2,
float_v & c3 )
inlinestatic

Get color values from float_v::size pixels 32-bit each (4 channels, 8 bit per channel). The color data is considered to be stored in the 3 least significant bytes of the pixel.

aligned controls whether the data is fetched using aligned instruction or not. 1) Fetching aligned data with unaligned instruction degrades performance. 2) Fetching unaligned data with aligned instruction causes #GP (General Protection Exception)

Definition at line 274 of file KoStreamedMath.h.

275 {
276 using U = typename std::conditional<aligned, xsimd::aligned_mode, xsimd::unaligned_mode>::type;
277
278 const auto data_i = uint_v::load(static_cast<const typename uint_v::value_type *>(data), U{});
279
280 const uint_v mask(0xFF);
281
282 c1 = xsimd::to_float(xsimd::bitwise_cast_compat<int>((data_i >> 16) & mask));
283 c2 = xsimd::to_float(xsimd::bitwise_cast_compat<int>((data_i >> 8) & mask));
284 c3 = xsimd::to_float(xsimd::bitwise_cast_compat<int>((data_i) & mask));
285 }
xsimd::batch< unsigned int, _impl > uint_v

◆ fetch_mask_8()

template<typename _impl >
static float_v KoStreamedMath< _impl >::fetch_mask_8 ( const quint8 * data)
inlinestatic

Get a vector containing first float_v::size values of mask. Each source mask element is considered to be a 8-bit integer

Definition at line 236 of file KoStreamedMath.h.

237 {
238 return xsimd::batch_cast<float>(xsimd::load_and_extend<int_v>(data));
239 }

◆ genericComposite()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor , int pixelSize>
static void KoStreamedMath< _impl >::genericComposite ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Composes src pixels into dst pixels. Is optimized for 32-bit-per-pixel colorspaces. Uses Compositor strategy parameter for doing actual math of the composition

Definition at line 325 of file KoStreamedMath.h.

326 {
327 const int vectorSize = static_cast<int>(float_v::size);
328 const qint32 vectorInc = pixelSize * vectorSize;
329 const qint32 linearInc = pixelSize;
330 qint32 srcVectorInc = vectorInc;
331 qint32 srcLinearInc = pixelSize;
332
333 quint8 *dstRowStart = params.dstRowStart;
334 const quint8 *maskRowStart = params.maskRowStart;
335 const quint8 *srcRowStart = params.srcRowStart;
336 typename Compositor::ParamsWrapper paramsWrapper(params);
337
338 if (!params.srcRowStride) {
339 if (pixelSize == 4) {
340 auto *buf = reinterpret_cast<uint_v *>(xsimd::vector_aligned_malloc<typename uint_v::value_type>(vectorSize));
341 *buf = uint_v(*(reinterpret_cast<const quint32 *>(srcRowStart)));
342 srcRowStart = reinterpret_cast<quint8 *>(buf);
343 srcLinearInc = 0;
344 srcVectorInc = 0;
345 } else {
346 auto *buf = xsimd::vector_aligned_malloc<quint8>(vectorInc);
347 quint8 *ptr = buf;
348
349 for (size_t i = 0; i < vectorSize; i++) {
350 memcpy(ptr, params.srcRowStart, pixelSize);
351 ptr += pixelSize;
352 }
353
354 srcRowStart = buf;
355 srcLinearInc = 0;
356 srcVectorInc = 0;
357 }
358 }
359#if BLOCKDEBUG
360 int totalBlockAlign = 0;
361 int totalBlockAlignedVector = 0;
362 int totalBlockUnalignedVector = 0;
363 int totalBlockRest = 0;
364#endif
365
366 for (qint32 r = params.rows; r > 0; --r) {
367 // Hint: Mask is allowed to be unaligned
368 const quint8 *mask = maskRowStart;
369
370 const quint8 *src = srcRowStart;
371 quint8 *dst = dstRowStart;
372
373 const int pixelsAlignmentMask = vectorSize * sizeof(float) - 1;
374 auto srcPtrValue = reinterpret_cast<uintptr_t>(src);
375 auto dstPtrValue = reinterpret_cast<uintptr_t>(dst);
376 uintptr_t srcAlignment = srcPtrValue & pixelsAlignmentMask;
377 uintptr_t dstAlignment = dstPtrValue & pixelsAlignmentMask;
378
379 // Uncomment if facing problems with alignment:
380 // Q_ASSERT_X(!(dstAlignment & 3), "Compositing",
381 // "Pixel data must be aligned on pixels borders!");
382
383 int blockAlign = params.cols;
384 int blockAlignedVector = 0;
385 int blockUnalignedVector = 0;
386 int blockRest = 0;
387
388 int *vectorBlock =
389 srcAlignment == dstAlignment || !srcVectorInc ? &blockAlignedVector : &blockUnalignedVector;
390
391 if (!dstAlignment) {
392 blockAlign = 0;
393 *vectorBlock = params.cols / vectorSize;
394 blockRest = params.cols % vectorSize;
395 } else if (params.cols > 2 * vectorSize) {
396 blockAlign = (vectorInc - dstAlignment) / pixelSize;
397 const int restCols = params.cols - blockAlign;
398 if (restCols > 0) {
399 *vectorBlock = restCols / vectorSize;
400 blockRest = restCols % vectorSize;
401 } else {
402 blockAlign = params.cols;
403 *vectorBlock = 0;
404 blockRest = 0;
405 }
406 }
407#if BLOCKDEBUG
408 totalBlockAlign += blockAlign;
409 totalBlockAlignedVector += blockAlignedVector;
410 totalBlockUnalignedVector += blockUnalignedVector;
411 totalBlockRest += blockRest;
412#endif
413
414 for (int i = 0; i < blockAlign; i++) {
415 Compositor::template compositeOnePixelScalar<useMask, _impl>(src,
416 dst,
417 mask,
418 params.opacity,
419 paramsWrapper);
420 src += srcLinearInc;
421 dst += linearInc;
422
423 if (useMask) {
424 mask++;
425 }
426 }
427
428 for (int i = 0; i < blockAlignedVector; i++) {
429 Compositor::template compositeVector<useMask, true, _impl>(src,
430 dst,
431 mask,
432 params.opacity,
433 paramsWrapper);
434 src += srcVectorInc;
435 dst += vectorInc;
436
437 if (useMask) {
438 mask += vectorSize;
439 }
440 }
441
442 for (int i = 0; i < blockUnalignedVector; i++) {
443 Compositor::template compositeVector<useMask, false, _impl>(src,
444 dst,
445 mask,
446 params.opacity,
447 paramsWrapper);
448 src += srcVectorInc;
449 dst += vectorInc;
450
451 if (useMask) {
452 mask += vectorSize;
453 }
454 }
455
456 for (int i = 0; i < blockRest; i++) {
457 Compositor::template compositeOnePixelScalar<useMask, _impl>(src,
458 dst,
459 mask,
460 params.opacity,
461 paramsWrapper);
462 src += srcLinearInc;
463 dst += linearInc;
464
465 if (useMask) {
466 mask++;
467 }
468 }
469
470 srcRowStart += params.srcRowStride;
471 dstRowStart += params.dstRowStride;
472
473 if (useMask) {
474 maskRowStart += params.maskRowStride;
475 }
476 }
477
478#if BLOCKDEBUG
479 dbgPigment << "I"
480 << "rows:" << params.rows << "\tpad(S):" << totalBlockAlign << "\tbav(V):" << totalBlockAlignedVector
481 << "\tbuv(V):" << totalBlockUnalignedVector << "\tres(S)"
482 << totalBlockRest; // << srcAlignment << dstAlignment;
483#endif
484
485 if (!params.srcRowStride) {
486 xsimd::vector_aligned_free(srcRowStart);
487 }
488 }
#define dbgPigment
void vector_aligned_free(const T *ptr) noexcept

References KoCompositeOp::ParameterInfo::cols, dbgPigment, KoCompositeOp::ParameterInfo::dstRowStart, KoCompositeOp::ParameterInfo::dstRowStride, KoCompositeOp::ParameterInfo::maskRowStart, KoCompositeOp::ParameterInfo::maskRowStride, KoCompositeOp::ParameterInfo::opacity, KoCompositeOp::ParameterInfo::rows, KoCompositeOp::ParameterInfo::srcRowStart, KoCompositeOp::ParameterInfo::srcRowStride, and xsimd::vector_aligned_free().

◆ genericComposite128()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite128 ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 497 of file KoStreamedMath.h.

498 {
499 genericComposite<useMask, useFlow, Compositor, 16>(params);
500 }

◆ genericComposite128_novector()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite128_novector ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 211 of file KoStreamedMath.h.

212 {
213 genericComposite_novector<useMask, useFlow, Compositor, 16>(params);
214 }

◆ genericComposite32()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite32 ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 491 of file KoStreamedMath.h.

492 {
493 genericComposite<useMask, useFlow, Compositor, 4>(params);
494 }

◆ genericComposite32_novector()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite32_novector ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 205 of file KoStreamedMath.h.

206 {
207 genericComposite_novector<useMask, useFlow, Compositor, 4>(params);
208 }

◆ genericComposite64()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite64 ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 503 of file KoStreamedMath.h.

504 {
505 genericComposite<useMask, useFlow, Compositor, 8>(params);
506 }

◆ genericComposite64_novector()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor >
static void KoStreamedMath< _impl >::genericComposite64_novector ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Definition at line 217 of file KoStreamedMath.h.

218 {
219 genericComposite_novector<useMask, useFlow, Compositor, 8>(params);
220 }

◆ genericComposite_novector()

template<typename _impl >
template<bool useMask, bool useFlow, class Compositor , int pixelSize>
static void KoStreamedMath< _impl >::genericComposite_novector ( const KoCompositeOp::ParameterInfo & params)
inlinestatic

Composes src into dst without using vector instructions

Definition at line 164 of file KoStreamedMath.h.

165 {
166 const qint32 linearInc = pixelSize;
167 qint32 srcLinearInc = params.srcRowStride ? pixelSize : 0;
168
169 quint8 *dstRowStart = params.dstRowStart;
170 const quint8 *maskRowStart = params.maskRowStart;
171 const quint8 *srcRowStart = params.srcRowStart;
172 typename Compositor::ParamsWrapper paramsWrapper(params);
173
174 for (qint32 r = params.rows; r > 0; --r) {
175 const quint8 *mask = maskRowStart;
176 const quint8 *src = srcRowStart;
177 quint8 *dst = dstRowStart;
178
179 int blockRest = params.cols;
180
181 for (int i = 0; i < blockRest; i++) {
182 Compositor::template compositeOnePixelScalar<useMask, _impl>(src,
183 dst,
184 mask,
185 params.opacity,
186 paramsWrapper);
187 src += srcLinearInc;
188 dst += linearInc;
189
190 if (useMask) {
191 mask++;
192 }
193 }
194
195 srcRowStart += params.srcRowStride;
196 dstRowStart += params.dstRowStride;
197
198 if (useMask) {
199 maskRowStart += params.maskRowStride;
200 }
201 }
202 }

References KoCompositeOp::ParameterInfo::cols, KoCompositeOp::ParameterInfo::dstRowStart, KoCompositeOp::ParameterInfo::dstRowStride, KoCompositeOp::ParameterInfo::maskRowStart, KoCompositeOp::ParameterInfo::maskRowStride, KoCompositeOp::ParameterInfo::opacity, KoCompositeOp::ParameterInfo::rows, KoCompositeOp::ParameterInfo::srcRowStart, and KoCompositeOp::ParameterInfo::srcRowStride.

◆ lerp_mixed_u8_float()

template<typename _impl >
static quint8 KoStreamedMath< _impl >::lerp_mixed_u8_float ( quint8 a,
quint8 b,
float alpha )
inlinestatic

Definition at line 227 of file KoStreamedMath.h.

228 {
229 return round_float_to_u8(float(b - a) * alpha + float(a));
230 }
static quint8 round_float_to_u8(float x)

References KoStreamedMath< _impl >::round_float_to_u8().

◆ round_float_to_u8()

template<typename _impl >
static quint8 KoStreamedMath< _impl >::round_float_to_u8 ( float x)
inlinestatic

Definition at line 222 of file KoStreamedMath.h.

223 {
225 }
static ALWAYS_INLINE result_type roundScalar(const float value)

References OptiRound< _impl, result_type >::roundScalar().

◆ write_channels_32()

template<typename _impl >
static void KoStreamedMath< _impl >::write_channels_32 ( void * data,
const float_v alpha,
const float_v c1,
const float_v c2,
const float_v c3 )
inlinestatic

Pack color and alpha values to float_v::size pixels 32-bit each (4 channels, 8 bit per channel). The color data is considered to be stored in the 3 least significant bytes of the pixel, alpha - in the most significant byte

NOTE: data must be aligned pointer!

Definition at line 296 of file KoStreamedMath.h.

297 {
298 const int_v mask(0xFF);
299
300 const auto v1 = (xsimd::nearbyint_as_int(alpha)) << 24;
301 const auto v2 = (xsimd::nearbyint_as_int(c1) & mask) << 16;
302 const auto v3 = (xsimd::nearbyint_as_int(c2) & mask) << 8;
303 const auto v4 = (xsimd::nearbyint_as_int(c3) & mask);
304 xsimd::store_aligned(static_cast<typename int_v::value_type *>(data), (v1 | v2) | (v3 | v4));
305 }
xsimd::batch< int, _impl > int_v

◆ write_channels_32_unaligned()

template<typename _impl >
static void KoStreamedMath< _impl >::write_channels_32_unaligned ( void * data,
const float_v alpha,
const float_v c1,
const float_v c2,
const float_v c3 )
inlinestatic

Definition at line 308 of file KoStreamedMath.h.

309 {
310 const int_v mask(0xFF);
311
312 const auto v1 = (xsimd::nearbyint_as_int(alpha)) << 24;
313 const auto v2 = (xsimd::nearbyint_as_int(c1) & mask) << 16;
314 const auto v3 = (xsimd::nearbyint_as_int(c2) & mask) << 8;
315 const auto v4 = (xsimd::nearbyint_as_int(c3) & mask);
316 xsimd::store_unaligned(static_cast<typename int_v::value_type *>(data), (v1 | v2) | (v3 | v4));
317 }

The documentation for this struct was generated from the following file: