Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Unified Diff: src/effects/gradients/Sk4fGradientPriv.h

Issue 1816883002: Refactor 4f gradients using trait templates (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/effects/gradients/Sk4fGradientBase.cpp ('k') | src/effects/gradients/Sk4fLinearGradient.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/effects/gradients/Sk4fGradientPriv.h
diff --git a/src/effects/gradients/Sk4fGradientPriv.h b/src/effects/gradients/Sk4fGradientPriv.h
index e9bc268b89cabc180d336e08d7fe0ba50a072503..4f71d3f14df6929d403872c1c22f7a014090ca42 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
« no previous file with comments | « src/effects/gradients/Sk4fGradientBase.cpp ('k') | src/effects/gradients/Sk4fLinearGradient.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698