aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkPM4fPriv.h
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2016-07-20 18:10:07 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-07-20 18:10:07 -0700
commit0c902473d64ef935a64d078f70bdc9334ab51427 (patch)
tree09a423ffe65a60d3571372d455df64068ac754a7 /src/core/SkPM4fPriv.h
parent456bf30d321292da7f15d1af35fd94fbb6a4bb59 (diff)
Correct sRGB <-> linear everywhere.
This trims the SkPM4fPriv methods down to just foolproof methods. (Anything trying to build these itself is probably wrong.) Things like Sk4f srgb_to_linear(Sk4f) can't really exist anymore, at least not efficiently, so this refactor is somewhat more invasive than you might think. Generally this means things using to_4f() are also making a misstep... that's gone too. It also does not make sense to try to play games with linear floats with 255 bias any more. That hack can't work with real sRGB coding. Rather than update them, I've removed a couple of L32 xfermode fast paths. I'd even rather drop it entirely... BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2163683002 CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot Review-Url: https://codereview.chromium.org/2163683002
Diffstat (limited to 'src/core/SkPM4fPriv.h')
-rw-r--r--src/core/SkPM4fPriv.h145
1 files changed, 34 insertions, 111 deletions
diff --git a/src/core/SkPM4fPriv.h b/src/core/SkPM4fPriv.h
index 57a44c1cb2..89a0caeb70 100644
--- a/src/core/SkPM4fPriv.h
+++ b/src/core/SkPM4fPriv.h
@@ -10,142 +10,65 @@
#include "SkColorPriv.h"
#include "SkPM4f.h"
+#include "SkSRGB.h"
-static inline float get_alpha(const Sk4f& f4) {
- return f4[SkPM4f::A];
+static inline Sk4f set_alpha(const Sk4f& px, float alpha) {
+ return { px[0], px[1], px[2], alpha };
}
-static inline Sk4f set_alpha(const Sk4f& f4, float alpha) {
- static_assert(3 == SkPM4f::A, "");
- return Sk4f(f4[0], f4[1], f4[2], alpha);
+static inline float get_alpha(const Sk4f& px) {
+ return px[3];
}
-static inline uint32_t to_4b(const Sk4f& f4) {
- uint32_t b4;
- SkNx_cast<uint8_t>(f4).store((uint8_t*)&b4);
- return b4;
-}
-
-static inline Sk4f to_4f(uint32_t b4) {
- return SkNx_cast<float>(Sk4b::Load((const uint8_t*)&b4));
-}
-
-static inline Sk4f to_4f_rgba(uint32_t b4) {
- return swizzle_rb_if_bgra(to_4f(b4));
-}
-
-static inline Sk4f srgb_to_linear(const Sk4f& s4) {
- return set_alpha(s4 * s4, get_alpha(s4));
-}
-
-static inline Sk4f linear_to_srgb(const Sk4f& l4) {
- return set_alpha(l4.rsqrt().invert(), get_alpha(l4));
-}
-
-static inline float srgb_to_linear(float x) {
- return x * x;
-}
-
-static inline float linear_to_srgb(float x) {
- return sqrtf(x);
-}
-
-static void assert_unit(float x) {
- SkASSERT(x >= 0 && x <= 1);
-}
-
-static inline float exact_srgb_to_linear(float x) {
- assert_unit(x);
- float linear;
- if (x <= 0.04045) {
- linear = x / 12.92f;
- } else {
- linear = powf((x + 0.055f) / 1.055f, 2.4f);
- }
- assert_unit(linear);
- return linear;
-}
-static inline float exact_linear_to_srgb(float x) {
- assert_unit(x);
- float srgb;
- if (x <= 0.0031308f) {
- srgb = x * 12.92f;
- } else {
- srgb = 1.055f * powf(x, 0.41666667f) - 0.055f;
- }
- assert_unit(srgb);
- return srgb;
+static inline Sk4f Sk4f_fromL32(uint32_t px) {
+ return SkNx_cast<float>(Sk4b::Load(&px)) * (1/255.0f);
}
-static inline Sk4f exact_srgb_to_linear(const Sk4f& x) {
- Sk4f linear(exact_srgb_to_linear(x[0]),
- exact_srgb_to_linear(x[1]),
- exact_srgb_to_linear(x[2]), 1);
- return set_alpha(linear, get_alpha(x));
+static inline Sk4f Sk4f_fromS32(uint32_t px) {
+ return { sk_linear_from_srgb[(px >> 0) & 0xff],
+ sk_linear_from_srgb[(px >> 8) & 0xff],
+ sk_linear_from_srgb[(px >> 16) & 0xff],
+ (1/255.0f) * (px >> 24) };
}
-static inline Sk4f exact_linear_to_srgb(const Sk4f& x) {
- Sk4f srgb(exact_linear_to_srgb(x[0]),
- exact_linear_to_srgb(x[1]),
- exact_linear_to_srgb(x[2]), 1);
- return set_alpha(srgb, get_alpha(x));
+static inline uint32_t Sk4f_toL32(const Sk4f& px) {
+ uint32_t l32;
+ SkNx_cast<uint8_t>(Sk4f_round(px * 255.0f)).store(&l32);
+ return l32;
}
-///////////////////////////////////////////////////////////////////////////////////////////////////
+static inline uint32_t Sk4f_toS32(const Sk4f& px) {
+ Sk4i rgb = sk_linear_to_srgb(px),
+ srgb = { rgb[0], rgb[1], rgb[2], (int)(255.0f * px[3] + 0.5f) };
-static inline Sk4f Sk4f_fromL32(uint32_t src) {
- return to_4f(src) * Sk4f(1.0f/255);
+ uint32_t s32;
+ SkNx_cast<uint8_t>(srgb).store(&s32);
+ return s32;
}
-static inline Sk4f Sk4f_fromS32(uint32_t src) {
- return srgb_to_linear(to_4f(src) * Sk4f(1.0f/255));
-}
-// Color handling:
+// SkColor handling:
// SkColor has an ordering of (b, g, r, a) if cast to an Sk4f, so the code swizzles r and b to
// produce the needed (r, g, b, a) ordering.
static inline Sk4f Sk4f_from_SkColor(SkColor color) {
return swizzle_rb(Sk4f_fromS32(color));
}
-static inline uint32_t Sk4f_toL32(const Sk4f& x4) {
- return to_4b(x4 * Sk4f(255) + Sk4f(0.5f));
+static inline void assert_unit(float x) {
+ SkASSERT(0 <= x && x <= 1);
}
-static inline uint32_t Sk4f_toS32(const Sk4f& x4) {
- return to_4b(linear_to_srgb(x4) * Sk4f(255) + Sk4f(0.5f));
-}
-
-static inline Sk4f exact_Sk4f_fromS32(uint32_t src) {
- return exact_srgb_to_linear(to_4f(src) * Sk4f(1.0f/255));
-}
-static inline uint32_t exact_Sk4f_toS32(const Sk4f& x4) {
- return to_4b(exact_linear_to_srgb(x4) * Sk4f(255) + Sk4f(0.5f));
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// An implementation of SrcOver from bytes to bytes in linear space that takes advantage of the
-// observation that the 255's cancel.
-// invA = 1 - (As / 255);
-//
-// R = 255 * sqrt((Rs/255)^2 + (Rd/255)^2 * invA)
-// => R = 255 * sqrt((Rs^2 + Rd^2 * invA)/255^2)
-// => R = sqrt(Rs^2 + Rd^2 * invA)
-// Note: src is assumed to be linear.
-static inline void srcover_blend_srgb8888_srgb_1(uint32_t* dst, const Sk4f& src) {
- Sk4f d = srgb_to_linear(to_4f(*dst));
- Sk4f invAlpha = 1.0f - Sk4f{src[SkPM4f::A]} * (1.0f / 255.0f);
- Sk4f r = linear_to_srgb(src + d * invAlpha) + 0.5f;
- *dst = to_4b(r);
-}
-
-static inline void srcover_srgb8888_srgb_1(uint32_t* dst, const uint32_t pixel) {
- if ((~pixel & 0xFF000000) == 0) {
- *dst = pixel;
- } else if ((pixel & 0xFF000000) != 0) {
- srcover_blend_srgb8888_srgb_1(dst, srgb_to_linear(to_4f(pixel)));
+static inline float exact_srgb_to_linear(float srgb) {
+ assert_unit(srgb);
+ float linear;
+ if (srgb <= 0.04045) {
+ linear = srgb / 12.92f;
+ } else {
+ linear = powf((srgb + 0.055f) / 1.055f, 2.4f);
}
+ assert_unit(linear);
+ return linear;
}
#endif