aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2017-05-04 10:57:40 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-04 15:21:39 +0000
commitb9641bd55a8f63757a63d9302755feb55d2e9502 (patch)
tree21cf4570aea3d430e9e5ef721d7e19f1b700dc5d
parent342a9fa8e1c0bccff0d2d1569042bce29f2bbe85 (diff)
force all colorfilters to implement 4f
high-contrast gms differ at most by 1 bit Bug: skia: Change-Id: I1308bd105020ea3cd5a30fd3dd322ed134fb5ed5 Reviewed-on: https://skia-review.googlesource.com/15249 Commit-Queue: Mike Reed <reed@google.com> Reviewed-by: Mike Klein <mtklein@chromium.org> Reviewed-by: Florin Malita <fmalita@chromium.org>
-rw-r--r--include/core/SkColorFilter.h2
-rw-r--r--include/effects/SkLumaColorFilter.h1
-rw-r--r--src/core/SkColorFilter.cpp18
-rw-r--r--src/core/SkPM4f.h9
-rw-r--r--src/effects/SkHighContrastFilter.cpp60
-rw-r--r--src/effects/SkLumaColorFilter.cpp24
-rw-r--r--src/effects/SkOverdrawColorFilter.cpp11
-rw-r--r--src/effects/SkOverdrawColorFilter.h1
-rw-r--r--src/effects/SkTableColorFilter.cpp48
-rw-r--r--src/utils/SkShadowUtils.cpp32
-rw-r--r--tools/sk_tool_utils.cpp3
11 files changed, 137 insertions, 72 deletions
diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h
index f843df7064..5845573c42 100644
--- a/include/core/SkColorFilter.h
+++ b/include/core/SkColorFilter.h
@@ -72,7 +72,7 @@ public:
*/
virtual void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) const = 0;
- virtual void filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const;
+ virtual void filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const = 0;
bool appendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
bool shaderIsOpaque) const;
diff --git a/include/effects/SkLumaColorFilter.h b/include/effects/SkLumaColorFilter.h
index 209394490d..cab675e5bc 100644
--- a/include/effects/SkLumaColorFilter.h
+++ b/include/effects/SkLumaColorFilter.h
@@ -29,6 +29,7 @@ public:
static sk_sp<SkColorFilter> Make();
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
+ void filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const override;
#if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index b82808d585..166d772668 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -50,24 +50,6 @@ bool SkColorFilter::onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAllo
return false;
}
-void SkColorFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const {
- const int N = 128;
- SkPMColor tmp[N];
- while (count > 0) {
- int n = SkTMin(count, N);
- for (int i = 0; i < n; ++i) {
- tmp[i] = src[i].toPMColor();
- }
- this->filterSpan(tmp, n, tmp);
- for (int i = 0; i < n; ++i) {
- result[i] = SkPM4f::FromPMColor(tmp[i]);
- }
- src += n;
- result += n;
- count -= n;
- }
-}
-
SkColor SkColorFilter::filterColor(SkColor c) const {
SkPMColor dst, src = SkPreMultiplyColor(c);
this->filterSpan(&src, 1, &dst);
diff --git a/src/core/SkPM4f.h b/src/core/SkPM4f.h
index f983101f41..ab2258b328 100644
--- a/src/core/SkPM4f.h
+++ b/src/core/SkPM4f.h
@@ -37,6 +37,15 @@ struct SkPM4f {
float b() const { return fVec[B]; }
float a() const { return fVec[A]; }
+ static SkPM4f FromPremulRGBA(float r, float g, float b, float a) {
+ SkPM4f p;
+ p.fVec[R] = r;
+ p.fVec[G] = g;
+ p.fVec[B] = b;
+ p.fVec[A] = a;
+ return p;
+ }
+
static SkPM4f From4f(const Sk4f& x) {
SkPM4f pm;
x.store(pm.fVec);
diff --git a/src/effects/SkHighContrastFilter.cpp b/src/effects/SkHighContrastFilter.cpp
index 5d92cdf0d0..2d827db751 100644
--- a/src/effects/SkHighContrastFilter.cpp
+++ b/src/effects/SkHighContrastFilter.cpp
@@ -6,7 +6,7 @@
*/
#include "SkHighContrastFilter.h"
-
+#include "SkPM4f.h"
#include "SkArenaAlloc.h"
#include "SkRasterPipeline.h"
#include "SkReadBuffer.h"
@@ -45,33 +45,18 @@ SkScalar Hue2RGB(SkScalar p, SkScalar q, SkScalar t) {
return p;
}
-uint8_t SkScalarToUint8Clamp(SkScalar f) {
- if (f <= 0) {
- return 0;
- } else if (f >= 1) {
- return 255;
- }
- return static_cast<unsigned char>(255 * f);
-}
-
SkScalar IncreaseContrast(SkScalar f, SkScalar contrast) {
SkScalar m = (1 + contrast) / (1 - contrast);
SkScalar b = (-0.5f * m + 0.5f);
return m * f + b;
}
-static SkPMColor ApplyHighContrastFilter(const SkHighContrastConfig& config,
- SkPMColor pmColor) {
- SkColor color = SkUnPreMultiply::PMColorToColor(pmColor);
- SkScalar rf = SkColorGetR(color) / 255.f;
- SkScalar gf = SkColorGetG(color) / 255.f;
- SkScalar bf = SkColorGetB(color) / 255.f;
-
+SkColor4f ApplyHighContrastFilter(const SkHighContrastConfig& config, const SkColor4f& src) {
// Apply a gamma of 2.0 so that the rest of the calculations
// happen roughly in linear space.
- rf *= rf;
- gf *= gf;
- bf *= bf;
+ float rf = src.fR * src.fR;
+ float gf = src.fG * src.fG;
+ float bf = src.fB * src.fB;
// Convert to grayscale using luminance coefficients.
if (config.fGrayscale) {
@@ -136,14 +121,7 @@ static SkPMColor ApplyHighContrastFilter(const SkHighContrastConfig& config,
}
// Convert back from linear to a color space with a gamma of ~2.0.
- rf = SkScalarSqrt(rf);
- gf = SkScalarSqrt(gf);
- bf = SkScalarSqrt(bf);
-
- return SkPremultiplyARGBInline(SkColorGetA(color),
- SkScalarToUint8Clamp(rf),
- SkScalarToUint8Clamp(gf),
- SkScalarToUint8Clamp(bf));
+ return SkColor4f::Pin(SkScalarSqrt(rf), SkScalarSqrt(gf), SkScalarSqrt(bf), src.fA);
}
} // namespace
@@ -164,8 +142,8 @@ public:
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif
- void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const
- override;
+ void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
+ void filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const override;
bool onAppendStages(SkRasterPipeline* p,
SkColorSpace* dst,
SkArenaAlloc* scratch,
@@ -186,10 +164,24 @@ private:
typedef SkColorFilter INHERITED;
};
-void SkHighContrast_Filter::filterSpan(const SkPMColor src[], int count,
- SkPMColor dst[]) const {
- for (int i = 0; i < count; ++i)
- dst[i] = ApplyHighContrastFilter(fConfig, src[i]);
+void SkHighContrast_Filter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
+ const float oneOver255 = 1.0f / 255;
+ for (int i = 0; i < count; ++i) {
+ SkColor color = SkUnPreMultiply::PMColorToColor(src[i]);
+ // be sure to NOT treat color as sRGB, as we are in legacy mode here
+ SkColor4f s4 {
+ SkColorGetR(color) * oneOver255, SkColorGetG(color) * oneOver255,
+ SkColorGetB(color) * oneOver255, SkColorGetA(color) * oneOver255,
+ };
+ SkColor4f d4 = ApplyHighContrastFilter(fConfig, s4);
+ dst[i] = d4.premul().toPMColor();
+ }
+}
+
+void SkHighContrast_Filter::filterSpan4f(const SkPM4f src[], int count, SkPM4f dst[]) const {
+ for (int i = 0; i < count; ++i) {
+ dst[i] = ApplyHighContrastFilter(fConfig, dst[i].unpremul()).premul();
+ }
}
bool SkHighContrast_Filter::onAppendStages(SkRasterPipeline* p,
diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp
index 2809c8b492..b2f6b47a69 100644
--- a/src/effects/SkLumaColorFilter.cpp
+++ b/src/effects/SkLumaColorFilter.cpp
@@ -6,7 +6,7 @@
*/
#include "SkLumaColorFilter.h"
-
+#include "SkPM4f.h"
#include "SkColorPriv.h"
#include "SkRasterPipeline.h"
#include "SkString.h"
@@ -17,8 +17,7 @@
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#endif
-void SkLumaColorFilter::filterSpan(const SkPMColor src[], int count,
- SkPMColor dst[]) const {
+void SkLumaColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
for (int i = 0; i < count; ++i) {
SkPMColor c = src[i];
@@ -37,6 +36,25 @@ void SkLumaColorFilter::filterSpan(const SkPMColor src[], int count,
}
}
+void SkLumaColorFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f dst[]) const {
+ for (int i = 0; i < count; ++i) {
+ /*
+ * While LuminanceToAlpha is defined to operate on un-premultiplied
+ * inputs, due to the final alpha scaling it can be computed based on
+ * premultipled components:
+ *
+ * LumA = (k1 * r / a + k2 * g / a + k3 * b / a) * a
+ * LumA = (k1 * r + k2 * g + k3 * b)
+ */
+ dst[i].fVec[SkPM4f::R] = 0;
+ dst[i].fVec[SkPM4f::G] = 0;
+ dst[i].fVec[SkPM4f::B] = 0;
+ dst[i].fVec[SkPM4f::A] = src[i].r() * SK_LUM_COEFF_R +
+ src[i].g() * SK_LUM_COEFF_G +
+ src[i].b() * SK_LUM_COEFF_B;
+ }
+}
+
bool SkLumaColorFilter::onAppendStages(SkRasterPipeline* p,
SkColorSpace* dst,
SkArenaAlloc* scratch,
diff --git a/src/effects/SkOverdrawColorFilter.cpp b/src/effects/SkOverdrawColorFilter.cpp
index 87bbc1069e..2bed180bcc 100644
--- a/src/effects/SkOverdrawColorFilter.cpp
+++ b/src/effects/SkOverdrawColorFilter.cpp
@@ -6,6 +6,7 @@
*/
#include "SkOverdrawColorFilter.h"
+#include "SkPM4f.h"
void SkOverdrawColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const {
for (int x = 0; x < count; x++) {
@@ -18,6 +19,16 @@ void SkOverdrawColorFilter::filterSpan(const SkPMColor src[], int count, SkPMCol
}
}
+void SkOverdrawColorFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f dst[]) const {
+ for (int i = 0; i < count; ++i) {
+ uint8_t alpha = (int)(src[i].a() * 255);
+ if (alpha >= kNumColors) {
+ alpha = kNumColors - 1;
+ }
+ dst[i] = SkPM4f::FromPMColor(fColors[alpha]);
+ }
+}
+
void SkOverdrawColorFilter::toString(SkString* str) const {
str->append("SkOverdrawColorFilter (");
for (int i = 0; i < kNumColors; i++) {
diff --git a/src/effects/SkOverdrawColorFilter.h b/src/effects/SkOverdrawColorFilter.h
index 6c5ce592f3..772e07c674 100644
--- a/src/effects/SkOverdrawColorFilter.h
+++ b/src/effects/SkOverdrawColorFilter.h
@@ -32,6 +32,7 @@ public:
#endif
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
+ void filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const override;
void toString(SkString* str) const override;
static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer);
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index 0253e60b59..d9ce98a7d8 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -1,12 +1,12 @@
/*
-* Copyright 2015 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
#include "SkTableColorFilter.h"
-
+#include "SkPM4f.h"
#include "SkArenaAlloc.h"
#include "SkBitmap.h"
#include "SkColorPriv.h"
@@ -90,6 +90,7 @@ public:
#endif
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
+ void filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const override;
SK_TO_STRING_OVERRIDE()
@@ -185,6 +186,41 @@ void SkTable_ColorFilter::filterSpan(const SkPMColor src[], int count, SkPMColor
}
}
+void SkTable_ColorFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f dst[]) const {
+ const uint8_t* table = fStorage;
+ const uint8_t* tableA = gIdentityTable;
+ const uint8_t* tableR = gIdentityTable;
+ const uint8_t* tableG = gIdentityTable;
+ const uint8_t* tableB = gIdentityTable;
+ if (fFlags & kA_Flag) {
+ tableA = table; table += 256;
+ }
+ if (fFlags & kR_Flag) {
+ tableR = table; table += 256;
+ }
+ if (fFlags & kG_Flag) {
+ tableG = table; table += 256;
+ }
+ if (fFlags & kB_Flag) {
+ tableB = table;
+ }
+
+ const float oneOver255 = 1.0f / 255;
+ for (int i = 0; i < count; ++i) {
+ SkColor4f c = src[i].unpremul();
+ int r = (int)(c.fR * 255.999) & 0xFF;
+ int g = (int)(c.fG * 255.999) & 0xFF;
+ int b = (int)(c.fB * 255.999) & 0xFF;
+ int a = (int)(c.fA * 255.999) & 0xFF;
+
+ SkColor4f d {
+ tableR[r] * oneOver255, tableG[g] * oneOver255,
+ tableB[b] * oneOver255, tableA[a] * oneOver255,
+ };
+ dst[i] = d.premul();
+ }
+}
+
#ifndef SK_IGNORE_TO_STRING
void SkTable_ColorFilter::toString(SkString* str) const {
const uint8_t* table = fStorage;
diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp
index 430ea2c3b1..ebd27e02b9 100644
--- a/src/utils/SkShadowUtils.cpp
+++ b/src/utils/SkShadowUtils.cpp
@@ -10,6 +10,7 @@
#include "SkColorFilter.h"
#include "SkColorPriv.h"
#include "SkPath.h"
+#include "SkPM4f.h"
#include "SkRandom.h"
#include "SkResourceCache.h"
#include "SkShadowTessellator.h"
@@ -36,6 +37,7 @@ public:
}
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
+ void filterSpan4f(const SkPM4f src[], int count, SkPM4f result[]) const override;
#if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
@@ -53,15 +55,18 @@ private:
typedef SkColorFilter INHERITED;
};
+static inline float eval_gaussian(float x) {
+ float factor = 1 - x;
+ return sk_float_exp(-factor * factor * 4) - 0.018f;
+}
+
static void build_table() {
SkDebugf("const uint8_t gByteExpU8Table[256] = {");
for (int i = 0; i <= 255; ++i) {
if (!(i % 8)) {
SkDebugf("\n");
}
- SkScalar factor = SK_Scalar1 - i / 255.f;
- factor = SkScalarExp(-factor * factor * 4) - 0.018f;
- int v = (int)(factor * 255.9f);
+ int v = (int)(eval_gaussian(i / 255.f) * 256);
SkDebugf(" 0x%02X,", v);
}
SkDebugf("\n};\n");
@@ -71,14 +76,14 @@ const uint8_t gByteExpU8Table[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04,
- 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07,
+ 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07,
0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09,
0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0D,
0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10, 0x10, 0x11,
0x11, 0x12, 0x12, 0x13, 0x14, 0x14, 0x15, 0x15,
0x16, 0x17, 0x17, 0x18, 0x19, 0x19, 0x1A, 0x1B,
0x1C, 0x1C, 0x1D, 0x1E, 0x1F, 0x1F, 0x20, 0x21,
- 0x22, 0x23, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x22, 0x23, 0x24, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39,
0x3A, 0x3B, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x42,
@@ -86,15 +91,15 @@ const uint8_t gByteExpU8Table[256] = {
0x4E, 0x50, 0x51, 0x53, 0x54, 0x55, 0x57, 0x58,
0x5A, 0x5B, 0x5D, 0x5E, 0x60, 0x61, 0x63, 0x64,
0x66, 0x68, 0x69, 0x6B, 0x6C, 0x6E, 0x70, 0x71,
- 0x73, 0x74, 0x76, 0x78, 0x79, 0x7B, 0x7D, 0x7E,
+ 0x73, 0x75, 0x76, 0x78, 0x79, 0x7B, 0x7D, 0x7F,
0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8A, 0x8C,
- 0x8E, 0x8F, 0x91, 0x93, 0x95, 0x96, 0x98, 0x9A,
+ 0x8E, 0x90, 0x91, 0x93, 0x95, 0x96, 0x98, 0x9A,
0x9C, 0x9D, 0x9F, 0xA1, 0xA2, 0xA4, 0xA6, 0xA8,
0xA9, 0xAB, 0xAD, 0xAE, 0xB0, 0xB2, 0xB3, 0xB5,
- 0xB7, 0xB8, 0xBA, 0xBB, 0xBD, 0xBF, 0xC0, 0xC2,
- 0xC3, 0xC5, 0xC6, 0xC8, 0xC9, 0xCB, 0xCC, 0xCE,
+ 0xB7, 0xB8, 0xBA, 0xBC, 0xBD, 0xBF, 0xC0, 0xC2,
+ 0xC3, 0xC5, 0xC7, 0xC8, 0xCA, 0xCB, 0xCD, 0xCE,
0xCF, 0xD1, 0xD2, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9,
- 0xDA, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE2, 0xE3,
+ 0xDA, 0xDC, 0xDD, 0xDE, 0xDF, 0xE1, 0xE2, 0xE3,
0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB,
0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF0, 0xF1, 0xF2,
0xF3, 0xF3, 0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7,
@@ -114,6 +119,13 @@ void SkGaussianColorFilter::filterSpan(const SkPMColor src[], int count, SkPMCol
}
}
+void SkGaussianColorFilter::filterSpan4f(const SkPM4f src[], int count, SkPM4f dst[]) const {
+ for (int i = 0; i < count; ++i) {
+ float v = eval_gaussian(src[i].a());
+ dst[i] = SkPM4f::FromPremulRGBA(v, v, v, v);
+ }
+}
+
sk_sp<SkFlattenable> SkGaussianColorFilter::CreateProc(SkReadBuffer&) {
return Make();
}
diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp
index 95f4cb1a6e..4b57a2cead 100644
--- a/tools/sk_tool_utils.cpp
+++ b/tools/sk_tool_utils.cpp
@@ -40,6 +40,9 @@ public:
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override {
SK_ABORT("SkSRGBColorFilter is only implemented for GPU");
}
+ void filterSpan4f(const SkPM4f src[], int count, SkPM4f dst[]) const override {
+ SK_ABORT("SkSRGBColorFilter is only implemented for GPU");
+ }
Factory getFactory() const override { return nullptr; }
#ifndef SK_IGNORE_TO_STRING