diff options
author | fmalita <fmalita@chromium.org> | 2016-03-18 10:28:23 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-18 10:28:23 -0700 |
commit | a928b288b3001eb34cc3c9caedbaac9a403b05ed (patch) | |
tree | efcad4a3e3f3a8fccf768a3796595cfa73638ab5 | |
parent | f28ad894272018fd2855e3f77ea1236ea0cce1c0 (diff) |
4f linear gradient shader blitters
Add F16 specializations to support writing to half-float dests.
Add color profile template arg across the board to support writing
to sRGB dests.
R=reed@google.com,mtklein@google.com,herb@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1808963005
Review URL: https://codereview.chromium.org/1808963005
-rw-r--r-- | src/core/SkPixmap.cpp | 6 | ||||
-rw-r--r-- | src/core/SkUtils.h | 10 | ||||
-rw-r--r-- | src/core/SkXfermodeU64.cpp | 6 | ||||
-rw-r--r-- | src/effects/gradients/Sk4fGradientBase.cpp | 25 | ||||
-rw-r--r-- | src/effects/gradients/Sk4fGradientBase.h | 5 | ||||
-rw-r--r-- | src/effects/gradients/Sk4fGradientPriv.h | 93 | ||||
-rw-r--r-- | src/effects/gradients/Sk4fLinearGradient.cpp | 186 | ||||
-rw-r--r-- | src/effects/gradients/Sk4fLinearGradient.h | 13 |
8 files changed, 244 insertions, 100 deletions
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp index aa1d213bf6..787c92252e 100644 --- a/src/core/SkPixmap.cpp +++ b/src/core/SkPixmap.cpp @@ -211,12 +211,6 @@ bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const { #include "SkNx.h" #include "SkHalf.h" -static void sk_memset64(uint64_t dst[], uint64_t value, int count) { - for (int i = 0; i < count; ++i) { - dst[i] = value; - } -} - bool SkPixmap::erase(const SkColor4f& origColor, const SkIRect* subset) const { SkPixmap pm; if (subset) { diff --git a/src/core/SkUtils.h b/src/core/SkUtils.h index 332ea8da7e..26f19e6906 100644 --- a/src/core/SkUtils.h +++ b/src/core/SkUtils.h @@ -32,6 +32,16 @@ static inline void sk_memset32(uint32_t buffer[], uint32_t value, int count) { } } +/** Similar to memset(), but it assigns a 64bit value into the buffer. + @param buffer The memory to have value copied into it + @param value The 64bit value to be copied into buffer + @param count The number of times value should be copied into the buffer. +*/ +static inline void sk_memset64(uint64_t buffer[], uint64_t value, int count) { + for (int i = 0; i < count; i++) { + buffer[i] = value; + } +} /////////////////////////////////////////////////////////////////////////////// #define kMaxBytesInUTF8Sequence 4 diff --git a/src/core/SkXfermodeU64.cpp b/src/core/SkXfermodeU64.cpp index 2609f89a2f..d3ddb2f02b 100644 --- a/src/core/SkXfermodeU64.cpp +++ b/src/core/SkXfermodeU64.cpp @@ -10,12 +10,6 @@ #include "SkUtils.h" #include "SkXfermode.h" -static void sk_memset64(uint64_t dst[], uint64_t value, int count) { - for (int i = 0; i < count; ++i) { - dst[i] = value; - } -} - enum DstType { kU16_Dst, kF16_Dst, diff --git a/src/effects/gradients/Sk4fGradientBase.cpp b/src/effects/gradients/Sk4fGradientBase.cpp index a729812790..43910108ff 100644 --- a/src/effects/gradients/Sk4fGradientBase.cpp +++ b/src/effects/gradients/Sk4fGradientBase.cpp @@ -6,7 +6,6 @@ */ #include "Sk4fGradientBase.h" -#include "Sk4fGradientPriv.h" #include <functional> @@ -277,22 +276,22 @@ GradientShaderBase4fContext::addMirrorIntervals(const SkGradientShaderBase& shad void SkGradientShaderBase:: GradientShaderBase4fContext::shadeSpan(int x, int y, SkPMColor dst[], int count) { if (fColorsArePremul) { - this->shadePremulSpan<SkPMColor, false>(x, y, dst, count); + this->shadePremulSpan<SkPMColor, ApplyPremul::False>(x, y, dst, count); } else { - this->shadePremulSpan<SkPMColor, true>(x, y, dst, count); + this->shadePremulSpan<SkPMColor, ApplyPremul::True>(x, y, dst, count); } } void SkGradientShaderBase:: GradientShaderBase4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { if (fColorsArePremul) { - this->shadePremulSpan<SkPM4f, false>(x, y, dst, count); + this->shadePremulSpan<SkPM4f, ApplyPremul::False>(x, y, dst, count); } else { - this->shadePremulSpan<SkPM4f, true>(x, y, dst, count); + this->shadePremulSpan<SkPM4f, ApplyPremul::True>(x, y, dst, count); } } -template<typename DstType, bool do_premul> +template<typename DstType, ApplyPremul premul> void SkGradientShaderBase:: GradientShaderBase4fContext::shadePremulSpan(int x, int y, DstType dst[], @@ -303,23 +302,23 @@ GradientShaderBase4fContext::shadePremulSpan(int x, int y, switch (shader.fTileMode) { case kClamp_TileMode: this->shadeSpanInternal<DstType, - do_premul, + premul, kClamp_TileMode>(x, y, dst, count); break; case kRepeat_TileMode: this->shadeSpanInternal<DstType, - do_premul, + premul, kRepeat_TileMode>(x, y, dst, count); break; case kMirror_TileMode: this->shadeSpanInternal<DstType, - do_premul, + premul, kMirror_TileMode>(x, y, dst, count); break; } } -template<typename DstType, bool do_premul, SkShader::TileMode tileMode> +template<typename DstType, ApplyPremul premul, SkShader::TileMode tileMode> void SkGradientShaderBase:: GradientShaderBase4fContext::shadeSpanInternal(int x, int y, DstType dst[], @@ -334,7 +333,7 @@ GradientShaderBase4fContext::shadeSpanInternal(int x, int y, this->mapTs(x, y, ts, n); for (int i = 0; i < n; ++i) { const Sk4f c = sampler.sample(ts[i]); - store<DstType, do_premul>(c, dst++); + store<DstType, kLinear_SkColorProfileType, premul>(c, dst++); } x += n; count -= n; @@ -424,8 +423,8 @@ private: } void loadIntervalData(const Interval* i) { - fCc = dst_swizzle<DstType>(i->fC0) * dst_component_scale<DstType>(); - fDc = dst_swizzle<DstType>(i->fDc) * dst_component_scale<DstType>(); + fCc = scale_for_dest<DstType, kLinear_SkColorProfileType>(dst_swizzle<DstType>(i->fC0)); + fDc = scale_for_dest<DstType, kLinear_SkColorProfileType>(dst_swizzle<DstType>(i->fDc)); } const Interval* fFirstInterval; diff --git a/src/effects/gradients/Sk4fGradientBase.h b/src/effects/gradients/Sk4fGradientBase.h index f745f8fc0b..03f7e6ef26 100644 --- a/src/effects/gradients/Sk4fGradientBase.h +++ b/src/effects/gradients/Sk4fGradientBase.h @@ -8,6 +8,7 @@ #ifndef Sk4fGradientBase_DEFINED #define Sk4fGradientBase_DEFINED +#include "Sk4fGradientPriv.h" #include "SkColor.h" #include "SkGradientShaderPriv.h" #include "SkMatrix.h" @@ -61,10 +62,10 @@ private: template<typename DstType, SkShader::TileMode tileMode> class TSampler; - template <typename DstType, bool do_premul> + template <typename DstType, ApplyPremul> void shadePremulSpan(int x, int y, DstType[], int count) const; - template <typename DstType, bool do_premul, SkShader::TileMode tileMode> + template <typename DstType, ApplyPremul, SkShader::TileMode tileMode> void shadeSpanInternal(int x, int y, DstType[], int count) const; }; diff --git a/src/effects/gradients/Sk4fGradientPriv.h b/src/effects/gradients/Sk4fGradientPriv.h index cf7a99b265..e9bc268b89 100644 --- a/src/effects/gradients/Sk4fGradientPriv.h +++ b/src/effects/gradients/Sk4fGradientPriv.h @@ -9,85 +9,115 @@ #define Sk4fGradientPriv_DEFINED #include "SkColor.h" +#include "SkHalf.h" +#include "SkImageInfo.h" #include "SkNx.h" #include "SkPM4f.h" +#include "SkPM4fPriv.h" // Templates shared by various 4f gradient flavors. namespace { +enum class ApplyPremul { True, False }; + inline Sk4f premul_4f(const Sk4f& c) { const float alpha = c[SkPM4f::A]; // FIXME: portable swizzle? return c * Sk4f(alpha, alpha, alpha, 1); } -template <bool do_premul> -inline SkPMColor trunc_from_255(const Sk4f& c) { +template <ApplyPremul premul> +inline SkPMColor trunc_from_4f_255(const Sk4f& c) { SkPMColor pmc; SkNx_cast<uint8_t>(c).store(&pmc); - if (do_premul) { + if (premul == ApplyPremul::True) { pmc = SkPreMultiplyARGB(SkGetPackedA32(pmc), SkGetPackedR32(pmc), SkGetPackedG32(pmc), SkGetPackedB32(pmc)); } return pmc; } -template<typename DstType, bool do_premul> +template<typename DstType, SkColorProfileType, ApplyPremul premul> void store(const Sk4f& color, DstType* dst); template<> -inline void store<SkPM4f, false>(const Sk4f& c, SkPM4f* dst) { +inline void store<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::False> + (const Sk4f& c, SkPM4f* dst) { c.store(dst); } template<> -inline void store<SkPM4f, true>(const Sk4f& c, SkPM4f* dst) { - store<SkPM4f, false>(premul_4f(c), dst); +inline void store<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::True> + (const Sk4f& c, SkPM4f* dst) { + premul_4f(c).store(dst); +} + +template<> +inline void store<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::False> + (const Sk4f& c, SkPMColor* dst) { + *dst = trunc_from_4f_255<ApplyPremul::False>(c); +} + +template<> +inline void store<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::True> + (const Sk4f& c, SkPMColor* dst) { + *dst = trunc_from_4f_255<ApplyPremul::True>(c); +} + +template<> +inline void store<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::False> + (const Sk4f& c, SkPMColor* dst) { + // FIXME: this assumes opaque colors. Handle unpremultiplication. + *dst = Sk4f_toS32(c); } template<> -inline void store<SkPMColor, false>(const Sk4f& c, SkPMColor* dst) { - *dst = trunc_from_255<false>(c); +inline void store<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::True> + (const Sk4f& c, SkPMColor* dst) { + *dst = Sk4f_toS32(premul_4f(c)); } template<> -inline void store<SkPMColor, true>(const Sk4f& c, SkPMColor* dst) { - *dst = trunc_from_255<true>(c); +inline void store<uint64_t, kLinear_SkColorProfileType, ApplyPremul::False> + (const Sk4f& c, uint64_t* dst) { + *dst = SkFloatToHalf_01(c); } -template<typename DstType, bool do_premul> +template<> +inline void store<uint64_t, kLinear_SkColorProfileType, ApplyPremul::True> + (const Sk4f& c, uint64_t* dst) { + *dst = SkFloatToHalf_01(premul_4f(c)); +} + +template<typename DstType, SkColorProfileType profile, ApplyPremul premul> inline void store4x(const Sk4f& c0, const Sk4f& c1, const Sk4f& c2, const Sk4f& c3, DstType* dst) { - store<DstType, do_premul>(c0, dst++); - store<DstType, do_premul>(c1, dst++); - store<DstType, do_premul>(c2, dst++); - store<DstType, do_premul>(c3, dst++); + store<DstType, profile, premul>(c0, dst++); + store<DstType, profile, premul>(c1, dst++); + store<DstType, profile, premul>(c2, dst++); + store<DstType, profile, premul>(c3, dst++); } template<> -inline void store4x<SkPMColor, false>(const Sk4f& c0, - const Sk4f& c1, - const Sk4f& c2, - const Sk4f& c3, - SkPMColor* dst) { +inline void store4x<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::False> + (const Sk4f& c0, const Sk4f& c1, + const Sk4f& c2, const Sk4f& c3, + SkPMColor* dst) { Sk4f_ToBytes((uint8_t*)dst, c0, c1, c2, c3); } -template<typename DstType> -float dst_component_scale(); - -template<> -inline float dst_component_scale<SkPM4f>() { - return 1; +template<typename DstType, SkColorProfileType> +Sk4f scale_for_dest(const Sk4f& c) { + return c; } template<> -inline float dst_component_scale<SkPMColor>() { - return 255; +inline Sk4f scale_for_dest<SkPMColor, kLinear_SkColorProfileType>(const Sk4f& c) { + return c * 255; } template<typename DstType> @@ -103,6 +133,11 @@ inline Sk4f dst_swizzle<SkPMColor>(const SkPM4f& c) { return c.to4f_pmorder(); } +template<> +inline Sk4f dst_swizzle<uint64_t>(const SkPM4f& c) { + return c.to4f(); +} + } #endif // Sk4fGradientPriv_DEFINED diff --git a/src/effects/gradients/Sk4fLinearGradient.cpp b/src/effects/gradients/Sk4fLinearGradient.cpp index 9bc84c4995..82b2fcc69b 100644 --- a/src/effects/gradients/Sk4fLinearGradient.cpp +++ b/src/effects/gradients/Sk4fLinearGradient.cpp @@ -5,16 +5,18 @@ * found in the LICENSE file. */ -#include "Sk4fGradientPriv.h" #include "Sk4fLinearGradient.h" +#include "SkUtils.h" +#include "SkXfermode.h" namespace { -template<typename DstType, bool do_premul> +template<typename DstType, SkColorProfileType, ApplyPremul> void fill(const Sk4f& c, DstType* dst, int n); template<> -void fill<SkPM4f, false>(const Sk4f& c, SkPM4f* dst, int n) { +void fill<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::False> + (const Sk4f& c, SkPM4f* dst, int n) { while (n > 0) { c.store(dst++); n--; @@ -22,21 +24,49 @@ void fill<SkPM4f, false>(const Sk4f& c, SkPM4f* dst, int n) { } template<> -void fill<SkPM4f, true>(const Sk4f& c, SkPM4f* dst, int n) { - fill<SkPM4f, false>(premul_4f(c), dst, n); +void fill<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::True> + (const Sk4f& c, SkPM4f* dst, int n) { + fill<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::False>(premul_4f(c), dst, n); } template<> -void fill<SkPMColor, false>(const Sk4f& c, SkPMColor* dst, int n) { - sk_memset32(dst, trunc_from_255<false>(c), n); +void fill<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::False> + (const Sk4f& c, SkPMColor* dst, int n) { + sk_memset32(dst, trunc_from_4f_255<ApplyPremul::False>(c), n); } template<> -void fill<SkPMColor, true>(const Sk4f& c, SkPMColor* dst, int n) { - sk_memset32(dst, trunc_from_255<true>(c), n); +void fill<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::True> + (const Sk4f& c, SkPMColor* dst, int n) { + sk_memset32(dst, trunc_from_4f_255<ApplyPremul::True>(c), n); } -template<typename DstType, bool do_premul> +template<> +void fill<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::False> + (const Sk4f& c, SkPMColor* dst, int n) { + // FIXME: this assumes opaque colors. Handle unpremultiplication. + sk_memset32(dst, Sk4f_toS32(c), n); +} + +template<> +void fill<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::True> + (const Sk4f& c, SkPMColor* dst, int n) { + sk_memset32(dst, Sk4f_toS32(premul_4f(c)), n); +} + +template<> +void fill<uint64_t, kLinear_SkColorProfileType, ApplyPremul::False> + (const Sk4f& c, uint64_t* dst, int n) { + sk_memset64(dst, SkFloatToHalf_01(c), n); +} + +template<> +void fill<uint64_t, kLinear_SkColorProfileType, ApplyPremul::True> + (const Sk4f& c, uint64_t* dst, int n) { + sk_memset64(dst, SkFloatToHalf_01(premul_4f(c)), n); +} + +template<typename DstType, SkColorProfileType profile, ApplyPremul premul> void ramp(const Sk4f& c, const Sk4f& dc, DstType* dst, int n) { SkASSERT(n > 0); @@ -49,7 +79,7 @@ void ramp(const Sk4f& c, const Sk4f& dc, DstType* dst, int n) { Sk4f c3 = c1 + dc2; while (n >= 4) { - store4x<DstType, do_premul>(c0, c1, c2, c3, dst); + store4x<DstType, profile, premul>(c0, c1, c2, c3, dst); dst += 4; c0 = c0 + dc4; @@ -59,12 +89,12 @@ void ramp(const Sk4f& c, const Sk4f& dc, DstType* dst, int n) { n -= 4; } if (n & 2) { - store<DstType, do_premul>(c0, dst++); - store<DstType, do_premul>(c1, dst++); + store<DstType, profile, premul>(c0, dst++); + store<DstType, profile, premul>(c1, dst++); c0 = c0 + dc2; } if (n & 1) { - store<DstType, do_premul>(c0, dst); + store<DstType, profile, premul>(c0, dst); } } @@ -163,9 +193,13 @@ LinearGradient4fContext::shadeSpan(int x, int y, SkPMColor dst[], int count) { // TODO: plumb dithering SkASSERT(count > 0); if (fColorsArePremul) { - this->shadePremulSpan<SkPMColor, false>(x, y, dst, count); + this->shadePremulSpan<SkPMColor, + kLinear_SkColorProfileType, + ApplyPremul::False>(x, y, dst, count); } else { - this->shadePremulSpan<SkPMColor, true>(x, y, dst, count); + this->shadePremulSpan<SkPMColor, + kLinear_SkColorProfileType, + ApplyPremul::True>(x, y, dst, count); } } @@ -179,13 +213,17 @@ LinearGradient4fContext::shadeSpan4f(int x, int y, SkPM4f dst[], int count) { // TONOTDO: plumb dithering SkASSERT(count > 0); if (fColorsArePremul) { - this->shadePremulSpan<SkPM4f, false>(x, y, dst, count); + this->shadePremulSpan<SkPM4f, + kLinear_SkColorProfileType, + ApplyPremul::False>(x, y, dst, count); } else { - this->shadePremulSpan<SkPM4f, true>(x, y, dst, count); + this->shadePremulSpan<SkPM4f, + kLinear_SkColorProfileType, + ApplyPremul::True>(x, y, dst, count); } } -template<typename DstType, bool do_premul> +template<typename DstType, SkColorProfileType profile, ApplyPremul premul> void SkLinearGradient:: LinearGradient4fContext::shadePremulSpan(int x, int y, DstType dst[], @@ -195,23 +233,27 @@ LinearGradient4fContext::shadePremulSpan(int x, int y, switch (shader.fTileMode) { case kClamp_TileMode: this->shadeSpanInternal<DstType, - do_premul, + profile, + premul, kClamp_TileMode>(x, y, dst, count); break; case kRepeat_TileMode: this->shadeSpanInternal<DstType, - do_premul, + profile, + premul, kRepeat_TileMode>(x, y, dst, count); break; case kMirror_TileMode: this->shadeSpanInternal<DstType, - do_premul, + profile, + premul, kMirror_TileMode>(x, y, dst, count); break; } } -template<typename DstType, bool do_premul, SkShader::TileMode tileMode> +template<typename DstType, SkColorProfileType profile, ApplyPremul premul, + SkShader::TileMode tileMode> void SkLinearGradient:: LinearGradient4fContext::shadeSpanInternal(int x, int y, DstType dst[], @@ -223,12 +265,12 @@ LinearGradient4fContext::shadeSpanInternal(int x, int y, &pt); const SkScalar fx = pinFx<tileMode>(pt.x()); const SkScalar dx = fDstToPos.getScaleX(); - LinearIntervalProcessor<DstType, tileMode> proc(fIntervals.begin(), - fIntervals.end() - 1, - this->findInterval(fx), - fx, - dx, - SkScalarNearlyZero(dx * count)); + LinearIntervalProcessor<DstType, profile, tileMode> proc(fIntervals.begin(), + fIntervals.end() - 1, + this->findInterval(fx), + fx, + dx, + SkScalarNearlyZero(dx * count)); while (count > 0) { // What we really want here is SkTPin(advance, 1, count) // but that's a significant perf hit for >> stops; investigate. @@ -243,12 +285,12 @@ LinearGradient4fContext::shadeSpanInternal(int x, int y, || (n == count && proc.currentRampIsZero())); if (proc.currentRampIsZero()) { - fill<DstType, do_premul>(proc.currentColor(), - dst, n); + fill<DstType, profile, premul>(proc.currentColor(), + dst, n); } else { - ramp<DstType, do_premul>(proc.currentColor(), - proc.currentColorGrad(), - dst, n); + ramp<DstType, profile, premul>(proc.currentColor(), + proc.currentColorGrad(), + dst, n); } proc.advance(SkIntToScalar(n)); @@ -257,7 +299,7 @@ LinearGradient4fContext::shadeSpanInternal(int x, int y, } } -template<typename DstType, SkShader::TileMode tileMode> +template<typename DstType, SkColorProfileType profile, SkShader::TileMode tileMode> class SkLinearGradient:: LinearGradient4fContext::LinearIntervalProcessor { public: @@ -267,8 +309,7 @@ public: SkScalar fx, SkScalar dx, bool is_vertical) - : fDstComponentScale(dst_component_scale<DstType>()) - , fAdvX((i->fP1 - fx) / dx) + : fAdvX((i->fP1 - fx) / dx) , fFirstInterval(firstInterval) , fLastInterval(lastInterval) , fInterval(i) @@ -308,8 +349,8 @@ private: fDc = dst_swizzle<DstType>(fInterval->fDc); fCc = dst_swizzle<DstType>(fInterval->fC0); fCc = fCc + fDc * Sk4f(t); - fCc = fCc * fDstComponentScale; - fDcDx = fDc * fDstComponentScale * Sk4f(fDx); + fCc = scale_for_dest<DstType, profile>(fCc); + fDcDx = scale_for_dest<DstType, profile>(fDc * Sk4f(fDx)); fZeroRamp = fIsVertical || fInterval->isZeroRamp(); } @@ -342,8 +383,6 @@ private: return advX; } - const Sk4f fDstComponentScale; // cached dst scale (PMC: 255, PM4f: 1) - // Current interval properties. Sk4f fDc; // local color gradient (dc/dt) Sk4f fDcDx; // dst color gradient (dc/dx) @@ -402,3 +441,68 @@ LinearGradient4fContext::mapTs(int x, int y, SkScalar ts[], int count) const { } } } + +SkShader::Context::BlitProc SkLinearGradient:: +LinearGradient4fContext::onChooseBlitProc(const SkImageInfo& info, BlitState* state) { + SkXfermode::Mode mode; + if (!SkXfermode::AsMode(state->fXfer, &mode)) { + return nullptr; + } + + const SkGradientShaderBase& shader = static_cast<const SkGradientShaderBase&>(fShader); + if (mode != SkXfermode::kSrc_Mode && + !(mode == SkXfermode::kSrcOver_Mode && shader.colorsAreOpaque())) { + return nullptr; + } + + switch (info.colorType()) { + case kN32_SkColorType: + return D32_BlitProc; + case kRGBA_F16_SkColorType: + return D64_BlitProc; + default: + return nullptr; + } +} + +void SkLinearGradient:: +LinearGradient4fContext::D32_BlitProc(BlitState* state, int x, int y, const SkPixmap& dst, + int count, const SkAlpha aa[]) { + // FIXME: ignoring coverage for now + const LinearGradient4fContext* ctx = + static_cast<const LinearGradient4fContext*>(state->fCtx); + + if (dst.info().isLinear()) { + if (ctx->fColorsArePremul) { + ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::False>( + x, y, dst.writable_addr32(x, y), count); + } else { + ctx->shadePremulSpan<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::True>( + x, y, dst.writable_addr32(x, y), count); + } + } else { + if (ctx->fColorsArePremul) { + ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::False>( + x, y, dst.writable_addr32(x, y), count); + } else { + ctx->shadePremulSpan<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::True>( + x, y, dst.writable_addr32(x, y), count); + } + } +} + +void SkLinearGradient:: +LinearGradient4fContext::D64_BlitProc(BlitState* state, int x, int y, const SkPixmap& dst, + int count, const SkAlpha aa[]) { + // FIXME: ignoring coverage for now + const LinearGradient4fContext* ctx = + static_cast<const LinearGradient4fContext*>(state->fCtx); + + if (ctx->fColorsArePremul) { + ctx->shadePremulSpan<uint64_t, kLinear_SkColorProfileType, ApplyPremul::False>( + x, y, dst.writable_addr64(x, y), count); + } else { + ctx->shadePremulSpan<uint64_t, kLinear_SkColorProfileType, ApplyPremul::True>( + x, y, dst.writable_addr64(x, y), count); + } +} diff --git a/src/effects/gradients/Sk4fLinearGradient.h b/src/effects/gradients/Sk4fLinearGradient.h index 67449fc7e9..9bce47c33d 100644 --- a/src/effects/gradients/Sk4fLinearGradient.h +++ b/src/effects/gradients/Sk4fLinearGradient.h @@ -22,22 +22,29 @@ public: protected: void mapTs(int x, int y, SkScalar ts[], int count) const override; + BlitProc onChooseBlitProc(const SkImageInfo&, BlitState*) override; + private: using INHERITED = GradientShaderBase4fContext; - template<typename DstType, TileMode> + template<typename DstType, SkColorProfileType, TileMode> class LinearIntervalProcessor; - template <typename DstType, bool premul> + template <typename DstType, SkColorProfileType, ApplyPremul> void shadePremulSpan(int x, int y, DstType[], int count) const; - template <typename DstType, bool premul, SkShader::TileMode tileMode> + template <typename DstType, SkColorProfileType, ApplyPremul, SkShader::TileMode tileMode> void shadeSpanInternal(int x, int y, DstType[], int count) const; const Interval* findInterval(SkScalar fx) const; bool isFast() const { return fDstToPosClass == kLinear_MatrixClass; } + static void D32_BlitProc(BlitState* state, int x, int y, const SkPixmap& dst, + int count, const SkAlpha aa[]); + static void D64_BlitProc(BlitState*, int x, int y, const SkPixmap& dst, + int count, const SkAlpha aa[]); + mutable const Interval* fCachedInterval; }; |