fmalita | 7e6fcf8 | 2016-03-10 11:18:43 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #ifndef Sk4fGradientPriv_DEFINED |
| 9 | #define Sk4fGradientPriv_DEFINED |
| 10 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 11 | #include "include/core/SkColor.h" |
| 12 | #include "include/core/SkImageInfo.h" |
| 13 | #include "include/private/SkColorData.h" |
| 14 | #include "include/private/SkHalf.h" |
| 15 | #include "include/private/SkNx.h" |
| 16 | #include "src/core/SkUtils.h" |
fmalita | 7e6fcf8 | 2016-03-10 11:18:43 -0800 | [diff] [blame] | 17 | |
| 18 | // Templates shared by various 4f gradient flavors. |
| 19 | |
Mike Klein | c33d614 | 2018-12-12 08:47:54 -0500 | [diff] [blame] | 20 | namespace { // NOLINT(google-build-namespaces) |
fmalita | 7e6fcf8 | 2016-03-10 11:18:43 -0800 | [diff] [blame] | 21 | |
fmalita | a928b28 | 2016-03-18 10:28:23 -0700 | [diff] [blame] | 22 | enum class ApplyPremul { True, False }; |
| 23 | |
fmalita | dc6c9bf | 2016-03-21 13:16:51 -0700 | [diff] [blame] | 24 | template <ApplyPremul> |
| 25 | struct PremulTraits; |
fmalita | 7e6fcf8 | 2016-03-10 11:18:43 -0800 | [diff] [blame] | 26 | |
fmalita | dc6c9bf | 2016-03-21 13:16:51 -0700 | [diff] [blame] | 27 | template <> |
| 28 | struct PremulTraits<ApplyPremul::False> { |
| 29 | static Sk4f apply(const Sk4f& c) { return c; } |
| 30 | }; |
fmalita | 7e6fcf8 | 2016-03-10 11:18:43 -0800 | [diff] [blame] | 31 | |
fmalita | dc6c9bf | 2016-03-21 13:16:51 -0700 | [diff] [blame] | 32 | template <> |
| 33 | struct PremulTraits<ApplyPremul::True> { |
| 34 | static Sk4f apply(const Sk4f& c) { |
Brian Osman | 781e350 | 2018-10-03 15:42:47 -0400 | [diff] [blame] | 35 | const float alpha = c[3]; |
fmalita | dc6c9bf | 2016-03-21 13:16:51 -0700 | [diff] [blame] | 36 | // FIXME: portable swizzle? |
| 37 | return c * Sk4f(alpha, alpha, alpha, 1); |
| 38 | } |
| 39 | }; |
fmalita | 7e6fcf8 | 2016-03-10 11:18:43 -0800 | [diff] [blame] | 40 | |
fmalita | dc6c9bf | 2016-03-21 13:16:51 -0700 | [diff] [blame] | 41 | // Struct encapsulating various dest-dependent ops: |
| 42 | // |
Brian Osman | 781e350 | 2018-10-03 15:42:47 -0400 | [diff] [blame] | 43 | // - load() Load a SkPMColor4f value into Sk4f. Normally called once per interval |
fmalita | dc6c9bf | 2016-03-21 13:16:51 -0700 | [diff] [blame] | 44 | // advance. Also applies a scale and swizzle suitable for DstType. |
| 45 | // |
| 46 | // - store() Store one Sk4f to dest. Optionally handles premul, color space |
| 47 | // conversion, etc. |
| 48 | // |
| 49 | // - store(count) Store the Sk4f value repeatedly to dest, count times. |
| 50 | // |
| 51 | // - store4x() Store 4 Sk4f values to dest (opportunistic optimization). |
| 52 | // |
Florin Malita | aa0ce82 | 2017-08-28 12:50:26 -0400 | [diff] [blame] | 53 | |
fmalita | dc6c9bf | 2016-03-21 13:16:51 -0700 | [diff] [blame] | 54 | template <ApplyPremul premul> |
Mike Klein | 541cbd4 | 2019-01-30 13:11:33 -0500 | [diff] [blame] | 55 | struct DstTraits { |
Florin Malita | aa0ce82 | 2017-08-28 12:50:26 -0400 | [diff] [blame] | 56 | using PM = PremulTraits<premul>; |
| 57 | |
| 58 | // For L32, prescaling by 255 saves a per-pixel multiplication when premul is not needed. |
Brian Osman | 781e350 | 2018-10-03 15:42:47 -0400 | [diff] [blame] | 59 | static Sk4f load(const SkPMColor4f& c) { |
| 60 | Sk4f c4f = swizzle_rb_if_bgra(Sk4f::Load(c.vec())); |
Florin Malita | aa0ce82 | 2017-08-28 12:50:26 -0400 | [diff] [blame] | 61 | return premul == ApplyPremul::False |
Brian Osman | 781e350 | 2018-10-03 15:42:47 -0400 | [diff] [blame] | 62 | ? c4f * Sk4f(255) |
| 63 | : c4f; |
Florin Malita | aa0ce82 | 2017-08-28 12:50:26 -0400 | [diff] [blame] | 64 | } |
| 65 | |
| 66 | static void store(const Sk4f& c, SkPMColor* dst, const Sk4f& bias) { |
| 67 | if (premul == ApplyPremul::False) { |
| 68 | // c is pre-scaled by 255 and pre-biased, just store. |
| 69 | SkNx_cast<uint8_t>(c).store(dst); |
| 70 | } else { |
| 71 | *dst = Sk4f_toL32(PM::apply(c) + bias); |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | static void store(const Sk4f& c, SkPMColor* dst, int n) { |
| 76 | SkPMColor pmc; |
| 77 | store(c, &pmc, Sk4f(0)); |
| 78 | sk_memset32(dst, pmc, n); |
| 79 | } |
| 80 | |
| 81 | static void store4x(const Sk4f& c0, const Sk4f& c1, |
| 82 | const Sk4f& c2, const Sk4f& c3, |
| 83 | SkPMColor* dst, |
| 84 | const Sk4f& bias0, |
| 85 | const Sk4f& bias1) { |
| 86 | if (premul == ApplyPremul::False) { |
| 87 | // colors are pre-scaled and pre-biased. |
| 88 | Sk4f_ToBytes((uint8_t*)dst, c0, c1, c2, c3); |
| 89 | } else { |
| 90 | store(c0, dst + 0, bias0); |
| 91 | store(c1, dst + 1, bias1); |
| 92 | store(c2, dst + 2, bias0); |
| 93 | store(c3, dst + 3, bias1); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | static Sk4f pre_lerp_bias(const Sk4f& bias) { |
| 98 | // We can apply the bias before interpolation when the colors are premultiplied. |
| 99 | return premul == ApplyPremul::False ? bias : 0; |
| 100 | } |
| 101 | }; |
| 102 | |
fmalita | dc6c9bf | 2016-03-21 13:16:51 -0700 | [diff] [blame] | 103 | } // anonymous namespace |
fmalita | 7e6fcf8 | 2016-03-10 11:18:43 -0800 | [diff] [blame] | 104 | |
| 105 | #endif // Sk4fGradientPriv_DEFINED |