aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/effects/gradients/Sk4fGradientPriv.h
diff options
context:
space:
mode:
authorGravatar fmalita <fmalita@chromium.org>2016-03-21 13:16:51 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-03-21 13:16:52 -0700
commitdc6c9bf91c158e89cd9d5ef19dfbf1da98c598a6 (patch)
treeb072c263452bed811ce7643fa53fb584c997359d /src/effects/gradients/Sk4fGradientPriv.h
parent66be626f7f3ddda243e51aa8f36398b26769a9b4 (diff)
Refactor 4f gradients using trait templates
Some 4f gradient housekeeping. 1) replace <DstPtrType, ColorProfile> specialization tuples with an enum covering all dest types (L32, S32, F16, F32) 2) group various template helpers into dest trait classes, specialized for each dest type (2a - conflate current dst_swizzle and scale_for_dest ops into one load op) 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=1816883002 Review URL: https://codereview.chromium.org/1816883002
Diffstat (limited to 'src/effects/gradients/Sk4fGradientPriv.h')
-rw-r--r--src/effects/gradients/Sk4fGradientPriv.h230
1 files changed, 141 insertions, 89 deletions
diff --git a/src/effects/gradients/Sk4fGradientPriv.h b/src/effects/gradients/Sk4fGradientPriv.h
index e9bc268b89..4f71d3f14d 100644
--- a/src/effects/gradients/Sk4fGradientPriv.h
+++ b/src/effects/gradients/Sk4fGradientPriv.h
@@ -14,6 +14,7 @@
#include "SkNx.h"
#include "SkPM4f.h"
#include "SkPM4fPriv.h"
+#include "SkUtils.h"
// Templates shared by various 4f gradient flavors.
@@ -21,11 +22,12 @@ 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);
-}
+enum class DstType {
+ L32, // Linear 32bit. Used for both shader/blitter paths.
+ S32, // SRGB 32bit. Used for the blitter path only.
+ F16, // Linear half-float. Used for blitters only.
+ F32, // Linear float. Used for shaders only.
+};
template <ApplyPremul premul>
inline SkPMColor trunc_from_4f_255(const Sk4f& c) {
@@ -38,106 +40,156 @@ inline SkPMColor trunc_from_4f_255(const Sk4f& c) {
return pmc;
}
-template<typename DstType, SkColorProfileType, ApplyPremul premul>
-void store(const Sk4f& color, DstType* dst);
+template <ApplyPremul>
+struct PremulTraits;
-template<>
-inline void store<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::False>
- (const Sk4f& c, SkPM4f* dst) {
- c.store(dst);
-}
+template <>
+struct PremulTraits<ApplyPremul::False> {
+ static Sk4f apply(const Sk4f& c) { return c; }
+};
-template<>
-inline void store<SkPM4f, kLinear_SkColorProfileType, ApplyPremul::True>
- (const Sk4f& c, SkPM4f* dst) {
- premul_4f(c).store(dst);
-}
+template <>
+struct PremulTraits<ApplyPremul::True> {
+ static Sk4f apply(const Sk4f& c) {
+ const float alpha = c[SkPM4f::A];
+ // FIXME: portable swizzle?
+ return c * Sk4f(alpha, alpha, alpha, 1);
+ }
+};
+
+// Struct encapsulating various dest-dependent ops:
+//
+// - load() Load a SkPM4f value into Sk4f. Normally called once per interval
+// advance. Also applies a scale and swizzle suitable for DstType.
+//
+// - store() Store one Sk4f to dest. Optionally handles premul, color space
+// conversion, etc.
+//
+// - store(count) Store the Sk4f value repeatedly to dest, count times.
+//
+// - store4x() Store 4 Sk4f values to dest (opportunistic optimization).
+//
+template <DstType, ApplyPremul premul = ApplyPremul::False>
+struct DstTraits;
-template<>
-inline void store<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::False>
- (const Sk4f& c, SkPMColor* dst) {
- *dst = trunc_from_4f_255<ApplyPremul::False>(c);
-}
+template <ApplyPremul premul>
+struct DstTraits<DstType::L32, premul> {
+ using Type = SkPMColor;
-template<>
-inline void store<SkPMColor, kLinear_SkColorProfileType, ApplyPremul::True>
- (const Sk4f& c, SkPMColor* dst) {
- *dst = trunc_from_4f_255<ApplyPremul::True>(c);
-}
+ // For L32, we prescale the values by 255 to save a per-pixel multiplication.
+ static Sk4f load(const SkPM4f& c) {
+ return c.to4f_pmorder() * Sk4f(255);
+ }
-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);
-}
+ static void store(const Sk4f& c, Type* dst) {
+ *dst = trunc_from_4f_255<premul>(c);
+ }
-template<>
-inline void store<SkPMColor, kSRGB_SkColorProfileType, ApplyPremul::True>
- (const Sk4f& c, SkPMColor* dst) {
- *dst = Sk4f_toS32(premul_4f(c));
-}
+ static void store(const Sk4f& c, Type* dst, int n) {
+ sk_memset32(dst, trunc_from_4f_255<premul>(c), n);
+ }
-template<>
-inline void store<uint64_t, kLinear_SkColorProfileType, ApplyPremul::False>
- (const Sk4f& c, uint64_t* dst) {
- *dst = SkFloatToHalf_01(c);
-}
+ static void store4x(const Sk4f& c0, const Sk4f& c1,
+ const Sk4f& c2, const Sk4f& c3,
+ Type* dst) {
+ if (premul == ApplyPremul::False) {
+ Sk4f_ToBytes((uint8_t*)dst, c0, c1, c2, c3);
+ } else {
+ store(c0, dst + 0);
+ store(c1, dst + 1);
+ store(c2, dst + 2);
+ store(c3, dst + 3);
+ }
+ }
+};
-template<>
-inline void store<uint64_t, kLinear_SkColorProfileType, ApplyPremul::True>
- (const Sk4f& c, uint64_t* dst) {
- *dst = SkFloatToHalf_01(premul_4f(c));
-}
+template <ApplyPremul premul>
+struct DstTraits<DstType::S32, premul> {
+ using PM = PremulTraits<premul>;
+ using Type = SkPMColor;
+
+ // TODO: prescale by something like (255^2, 255^2, 255^2, 255) and use
+ // linear_to_srgb to save a mult in store?
+ static Sk4f load(const SkPM4f& c) {
+ return c.to4f_pmorder();
+ }
-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, profile, premul>(c0, dst++);
- store<DstType, profile, premul>(c1, dst++);
- store<DstType, profile, premul>(c2, dst++);
- store<DstType, profile, premul>(c3, dst++);
-}
+ static void store(const Sk4f& c, Type* dst) {
+ // FIXME: this assumes opaque colors. Handle unpremultiplication.
+ *dst = Sk4f_toS32(PM::apply(c));
+ }
-template<>
-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);
-}
+ static void store(const Sk4f& c, Type* dst, int n) {
+ sk_memset32(dst, Sk4f_toS32(PM::apply(c)), n);
+ }
-template<typename DstType, SkColorProfileType>
-Sk4f scale_for_dest(const Sk4f& c) {
- return c;
-}
+ static void store4x(const Sk4f& c0, const Sk4f& c1,
+ const Sk4f& c2, const Sk4f& c3,
+ Type* dst) {
+ store(c0, dst + 0);
+ store(c1, dst + 1);
+ store(c2, dst + 2);
+ store(c3, dst + 3);
+ }
+};
-template<>
-inline Sk4f scale_for_dest<SkPMColor, kLinear_SkColorProfileType>(const Sk4f& c) {
- return c * 255;
-}
+template <ApplyPremul premul>
+struct DstTraits<DstType::F16, premul> {
+ using PM = PremulTraits<premul>;
+ using Type = uint64_t;
-template<typename DstType>
-Sk4f dst_swizzle(const SkPM4f&);
+ static Sk4f load(const SkPM4f& c) {
+ return c.to4f();
+ }
-template<>
-inline Sk4f dst_swizzle<SkPM4f>(const SkPM4f& c) {
- return c.to4f();
-}
+ static void store(const Sk4f& c, Type* dst) {
+ *dst = SkFloatToHalf_01(PM::apply(c));
+ }
-template<>
-inline Sk4f dst_swizzle<SkPMColor>(const SkPM4f& c) {
- return c.to4f_pmorder();
-}
+ static void store(const Sk4f& c, Type* dst, int n) {
+ sk_memset64(dst, SkFloatToHalf_01(PM::apply(c)), n);
+ }
-template<>
-inline Sk4f dst_swizzle<uint64_t>(const SkPM4f& c) {
- return c.to4f();
-}
+ static void store4x(const Sk4f& c0, const Sk4f& c1,
+ const Sk4f& c2, const Sk4f& c3,
+ Type* dst) {
+ store(c0, dst + 0);
+ store(c1, dst + 1);
+ store(c2, dst + 2);
+ store(c3, dst + 3);
+ }
+};
-}
+template <ApplyPremul premul>
+struct DstTraits<DstType::F32, premul> {
+ using PM = PremulTraits<premul>;
+ using Type = SkPM4f;
+
+ static Sk4f load(const SkPM4f& c) {
+ return c.to4f();
+ }
+
+ static void store(const Sk4f& c, Type* dst) {
+ PM::apply(c).store(dst->fVec);
+ }
+
+ static void store(const Sk4f& c, Type* dst, int n) {
+ const Sk4f pmc = PM::apply(c);
+ for (int i = 0; i < n; ++i) {
+ pmc.store(dst[i].fVec);
+ }
+ }
+
+ static void store4x(const Sk4f& c0, const Sk4f& c1,
+ const Sk4f& c2, const Sk4f& c3,
+ Type* dst) {
+ store(c0, dst + 0);
+ store(c1, dst + 1);
+ store(c2, dst + 2);
+ store(c3, dst + 3);
+ }
+};
+
+} // anonymous namespace
#endif // Sk4fGradientPriv_DEFINED