GrConstColorProcessor uses 4f colors in the destination space
Many places that construct one are explicitly specifying opaque white or
transparent black, which we can assume (based on the semantics of the
operation) should remain (0,0,0,0) or (1,1,1,1), so that's simple.
In other cases, we convert our source color to destination space.
One wrinkle is tht SkColorFilter now needs to know the destination color
space, due to SkModeColorFilter.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3903
Change-Id: I4969c0260588f4021300733f601b47dc606adf79
Reviewed-on: https://skia-review.googlesource.com/3903
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp b/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp
index 091a55b..c0652bf 100644
--- a/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp
+++ b/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp
@@ -1334,13 +1334,17 @@
if (0 == fNumOctaves) {
if (kFractalNoise_Type == fType) {
// Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
+ // TODO: Either treat the output of this shader as sRGB or allow client to specify a
+ // color space of the noise. Either way, this case (and the GLSL) need to convert to
+ // the destination.
sk_sp<GrFragmentProcessor> inner(
- GrConstColorProcessor::Make(0x80404040,
+ GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
GrConstColorProcessor::kModulateRGBA_InputMode));
return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
}
// Emit zero.
- return GrConstColorProcessor::Make(0x0, GrConstColorProcessor::kIgnore_InputMode);
+ return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+ GrConstColorProcessor::kIgnore_InputMode);
}
SkAutoTUnref<GrTexture> permutationsTexture(
diff --git a/gm/constcolorprocessor.cpp b/gm/constcolorprocessor.cpp
index ef23f78..b4983dc 100644
--- a/gm/constcolorprocessor.cpp
+++ b/gm/constcolorprocessor.cpp
@@ -103,7 +103,7 @@
&grPaint));
GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m;
- GrColor color = kColors[procColor];
+ GrColor4f color = GrColor4f::FromGrColor(kColors[procColor]);
sk_sp<GrFragmentProcessor> fp(GrConstColorProcessor::Make(color, mode));
grPaint.addColorFragmentProcessor(std::move(fp));
diff --git a/include/core/SkColorFilter.h b/include/core/SkColorFilter.h
index 4857398..f265998 100644
--- a/include/core/SkColorFilter.h
+++ b/include/core/SkColorFilter.h
@@ -16,6 +16,7 @@
class GrContext;
class GrFragmentProcessor;
class SkBitmap;
+class SkColorSpace;
class SkRasterPipeline;
/**
@@ -144,7 +145,8 @@
*
* A null return indicates that the color filter isn't implemented for the GPU backend.
*/
- virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const;
+ virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*,
+ SkColorSpace* dstColorSpace) const;
#endif
bool affectsTransparentBlack() const {
diff --git a/include/effects/SkColorCubeFilter.h b/include/effects/SkColorCubeFilter.h
index f30371d..ea69d4d 100644
--- a/include/effects/SkColorCubeFilter.h
+++ b/include/effects/SkColorCubeFilter.h
@@ -26,7 +26,7 @@
uint32_t getFlags() const override;
#if SK_SUPPORT_GPU
- sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override;
+ sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif
SK_TO_STRING_OVERRIDE()
diff --git a/include/effects/SkGammaColorFilter.h b/include/effects/SkGammaColorFilter.h
index b98838e..72c464e 100644
--- a/include/effects/SkGammaColorFilter.h
+++ b/include/effects/SkGammaColorFilter.h
@@ -25,7 +25,7 @@
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
#if SK_SUPPORT_GPU
- sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override;
+ sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif
SK_TO_STRING_OVERRIDE()
diff --git a/include/effects/SkLumaColorFilter.h b/include/effects/SkLumaColorFilter.h
index ac4afa2..9625435 100644
--- a/include/effects/SkLumaColorFilter.h
+++ b/include/effects/SkLumaColorFilter.h
@@ -29,7 +29,7 @@
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
#if SK_SUPPORT_GPU
- sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override;
+ sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif
SK_TO_STRING_OVERRIDE()
diff --git a/include/gpu/GrColor.h b/include/gpu/GrColor.h
index f526717..cde9b74 100644
--- a/include/gpu/GrColor.h
+++ b/include/gpu/GrColor.h
@@ -185,6 +185,24 @@
fRGBA[3] = a;
}
+ enum Illegal_Constructor {
+ kIllegalConstructor
+ };
+ GrColor4f(Illegal_Constructor) {
+ fRGBA[0] = SK_FloatNaN;
+ fRGBA[1] = SK_FloatNaN;
+ fRGBA[2] = SK_FloatNaN;
+ fRGBA[3] = SK_FloatNaN;
+ }
+
+ static GrColor4f OpaqueWhite() {
+ return GrColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+
+ static GrColor4f TransparentBlack() {
+ return GrColor4f(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+
static GrColor4f FromGrColor(GrColor color) {
GrColor4f result;
GrColorToRGBAFloat(color, result.fRGBA);
diff --git a/include/gpu/effects/GrConstColorProcessor.h b/include/gpu/effects/GrConstColorProcessor.h
index e9781bb..1d23fc3 100644
--- a/include/gpu/effects/GrConstColorProcessor.h
+++ b/include/gpu/effects/GrConstColorProcessor.h
@@ -26,7 +26,7 @@
};
static const int kInputModeCnt = kLastInputMode + 1;
- static sk_sp<GrFragmentProcessor> Make(GrColor color, InputMode mode) {
+ static sk_sp<GrFragmentProcessor> Make(GrColor4f color, InputMode mode) {
return sk_sp<GrFragmentProcessor>(new GrConstColorProcessor(color, mode));
}
@@ -34,16 +34,16 @@
SkString dumpInfo() const override {
SkString str;
- str.appendf("Color: 0x%08x", fColor);
+ str.appendf("Color: 0x%08x", fColor.toGrColor());
return str;
}
- GrColor color() const { return fColor; }
+ GrColor4f color() const { return fColor; }
InputMode inputMode() const { return fMode; }
private:
- GrConstColorProcessor(GrColor color, InputMode mode) : fColor(color), fMode(mode) {
+ GrConstColorProcessor(GrColor4f color, InputMode mode) : fColor(color), fMode(mode) {
this->initClassID<GrConstColorProcessor>();
}
@@ -57,7 +57,7 @@
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
- GrColor fColor;
+ GrColor4f fColor;
InputMode fMode;
typedef GrFragmentProcessor INHERITED;
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index 31c0ddb..b23b100 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -32,7 +32,7 @@
}
#if SK_SUPPORT_GPU
-sk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*) const {
+sk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const {
return nullptr;
}
#endif
@@ -114,9 +114,10 @@
#endif
#if SK_SUPPORT_GPU
- sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context) const override {
- sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context));
- sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context));
+ sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context,
+ SkColorSpace* dstColorSpace) const override {
+ sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context, dstColorSpace));
+ sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context, dstColorSpace));
if (!innerFP || !outerFP) {
return nullptr;
}
diff --git a/src/core/SkColorFilterShader.cpp b/src/core/SkColorFilterShader.cpp
index 8bf82b8..4090a18 100644
--- a/src/core/SkColorFilterShader.cpp
+++ b/src/core/SkColorFilterShader.cpp
@@ -104,7 +104,8 @@
return nullptr;
}
- sk_sp<GrFragmentProcessor> fp2(fFilter->asFragmentProcessor(args.fContext));
+ sk_sp<GrFragmentProcessor> fp2(fFilter->asFragmentProcessor(args.fContext,
+ args.fDstColorSpace));
if (!fp2) {
return fp1;
}
diff --git a/src/core/SkColorMatrixFilterRowMajor255.cpp b/src/core/SkColorMatrixFilterRowMajor255.cpp
index 29a3f10..9517704 100644
--- a/src/core/SkColorMatrixFilterRowMajor255.cpp
+++ b/src/core/SkColorMatrixFilterRowMajor255.cpp
@@ -396,7 +396,8 @@
return ColorMatrixEffect::Make(colorMatrix);
}
-sk_sp<GrFragmentProcessor> SkColorMatrixFilterRowMajor255::asFragmentProcessor(GrContext*) const {
+sk_sp<GrFragmentProcessor> SkColorMatrixFilterRowMajor255::asFragmentProcessor(
+ GrContext*, SkColorSpace*) const {
return ColorMatrixEffect::Make(fMatrix);
}
diff --git a/src/core/SkColorMatrixFilterRowMajor255.h b/src/core/SkColorMatrixFilterRowMajor255.h
index c115885..0372f67 100644
--- a/src/core/SkColorMatrixFilterRowMajor255.h
+++ b/src/core/SkColorMatrixFilterRowMajor255.h
@@ -25,7 +25,7 @@
sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter>) const override;
#if SK_SUPPORT_GPU
- sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override;
+ sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif
SK_TO_STRING_OVERRIDE()
diff --git a/src/core/SkColorShader.cpp b/src/core/SkColorShader.cpp
index cfa071f..e66ae20 100644
--- a/src/core/SkColorShader.cpp
+++ b/src/core/SkColorShader.cpp
@@ -89,8 +89,8 @@
#include "SkGr.h"
#include "effects/GrConstColorProcessor.h"
-sk_sp<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const AsFPArgs&) const {
- GrColor color = SkColorToPremulGrColor(fColor);
+sk_sp<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const AsFPArgs& args) const {
+ GrColor4f color = SkColorToPremulGrColor4f(fColor, args.fDstColorSpace);
return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode);
}
@@ -208,10 +208,14 @@
#include "SkGr.h"
#include "effects/GrConstColorProcessor.h"
-sk_sp<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const AsFPArgs&) const {
- // TODO: how to communicate color4f to Gr
- GrColor color = SkColorToPremulGrColor(fCachedByteColor);
- return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode);
+sk_sp<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const AsFPArgs& args) const {
+ sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(),
+ args.fDstColorSpace);
+ GrColor4f color = GrColor4f::FromSkColor4f(fColor4);
+ if (colorSpaceXform) {
+ color = colorSpaceXform->apply(color);
+ }
+ return GrConstColorProcessor::Make(color.premul(), GrConstColorProcessor::kModulateA_InputMode);
}
#endif
diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp
index 7696e16..51e30ea 100644
--- a/src/core/SkComposeShader.cpp
+++ b/src/core/SkComposeShader.cpp
@@ -192,7 +192,7 @@
switch (mode) {
case SkXfermode::kClear_Mode:
- return GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK,
+ return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode);
break;
case SkXfermode::kSrc_Mode:
diff --git a/src/core/SkModeColorFilter.cpp b/src/core/SkModeColorFilter.cpp
index 8da7c00..977e87f 100644
--- a/src/core/SkModeColorFilter.cpp
+++ b/src/core/SkModeColorFilter.cpp
@@ -106,13 +106,14 @@
#include "effects/GrConstColorProcessor.h"
#include "SkGr.h"
-sk_sp<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor(GrContext*) const {
+sk_sp<GrFragmentProcessor> SkModeColorFilter::asFragmentProcessor(
+ GrContext*, SkColorSpace* dstColorSpace) const {
if (SkXfermode::kDst_Mode == fMode) {
return nullptr;
}
sk_sp<GrFragmentProcessor> constFP(
- GrConstColorProcessor::Make(SkColorToPremulGrColor(fColor),
+ GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpace),
GrConstColorProcessor::kIgnore_InputMode));
sk_sp<GrFragmentProcessor> fp(
GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode));
diff --git a/src/core/SkModeColorFilter.h b/src/core/SkModeColorFilter.h
index c9d75ab..cd8fe7c 100644
--- a/src/core/SkModeColorFilter.h
+++ b/src/core/SkModeColorFilter.h
@@ -32,7 +32,7 @@
#endif
#if SK_SUPPORT_GPU
- sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override;
+ sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
diff --git a/src/effects/SkColorCubeFilter.cpp b/src/effects/SkColorCubeFilter.cpp
index 3eb70d32..2a921d8 100644
--- a/src/effects/SkColorCubeFilter.cpp
+++ b/src/effects/SkColorCubeFilter.cpp
@@ -298,7 +298,8 @@
const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
}
-sk_sp<GrFragmentProcessor> SkColorCubeFilter::asFragmentProcessor(GrContext* context) const {
+sk_sp<GrFragmentProcessor> SkColorCubeFilter::asFragmentProcessor(GrContext* context,
+ SkColorSpace*) const {
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key;
GrUniqueKey::Builder builder(&key, kDomain, 2);
diff --git a/src/effects/SkGammaColorFilter.cpp b/src/effects/SkGammaColorFilter.cpp
index eba8e32..181ab77 100644
--- a/src/effects/SkGammaColorFilter.cpp
+++ b/src/effects/SkGammaColorFilter.cpp
@@ -50,7 +50,8 @@
#endif
#if SK_SUPPORT_GPU
-sk_sp<GrFragmentProcessor> SkGammaColorFilter::asFragmentProcessor(GrContext*) const {
+sk_sp<GrFragmentProcessor> SkGammaColorFilter::asFragmentProcessor(GrContext*,
+ SkColorSpace*) const {
return GrGammaEffect::Make(fGamma);
}
#endif
diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp
index ec94eca..19b2c72 100644
--- a/src/effects/SkLumaColorFilter.cpp
+++ b/src/effects/SkLumaColorFilter.cpp
@@ -111,7 +111,7 @@
}
};
-sk_sp<GrFragmentProcessor> SkLumaColorFilter::asFragmentProcessor(GrContext*) const {
+sk_sp<GrFragmentProcessor> SkLumaColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const {
return LumaColorFilterEffect::Make();
}
#endif
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index 5dbdab1..06bf813 100644
--- a/src/effects/SkPerlinNoiseShader.cpp
+++ b/src/effects/SkPerlinNoiseShader.cpp
@@ -906,13 +906,17 @@
if (0 == fNumOctaves) {
if (kFractalNoise_Type == fType) {
// Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
+ // TODO: Either treat the output of this shader as sRGB or allow client to specify a
+ // color space of the noise. Either way, this case (and the GLSL) need to convert to
+ // the destination.
sk_sp<GrFragmentProcessor> inner(
- GrConstColorProcessor::Make(0x80404040,
+ GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
GrConstColorProcessor::kModulateRGBA_InputMode));
return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
}
// Emit zero.
- return GrConstColorProcessor::Make(0x0, GrConstColorProcessor::kIgnore_InputMode);
+ return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+ GrConstColorProcessor::kIgnore_InputMode);
}
// Either we don't stitch tiles, either we have a valid tile size
diff --git a/src/effects/SkTableColorFilter.cpp b/src/effects/SkTableColorFilter.cpp
index ebf646b..7591088 100644
--- a/src/effects/SkTableColorFilter.cpp
+++ b/src/effects/SkTableColorFilter.cpp
@@ -49,7 +49,7 @@
sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter> inner) const override;
#if SK_SUPPORT_GPU
- sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override;
+ sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
@@ -561,13 +561,14 @@
(flags & (1 << 2)) ? luts[2] : nullptr,
(flags & (1 << 3)) ? luts[3] : nullptr
));
-
- sk_sp<GrFragmentProcessor> fp = filter->asFragmentProcessor(d->fContext);
+ sk_sp<SkColorSpace> colorSpace = GrTest::TestColorSpace(d->fRandom);
+ sk_sp<GrFragmentProcessor> fp = filter->asFragmentProcessor(d->fContext, colorSpace.get());
SkASSERT(fp);
return fp;
}
-sk_sp<GrFragmentProcessor> SkTable_ColorFilter::asFragmentProcessor(GrContext* context) const {
+sk_sp<GrFragmentProcessor> SkTable_ColorFilter::asFragmentProcessor(GrContext* context,
+ SkColorSpace*) const {
SkBitmap bitmap;
this->asComponentTable(&bitmap);
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index b073516..2ceba4b 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -268,8 +268,8 @@
GrTextureDomain::kDecal_Mode,
GrTextureParams::kNone_FilterMode);
} else {
- bgFP = GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK,
- GrConstColorProcessor::kIgnore_InputMode);
+ bgFP = GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+ GrConstColorProcessor::kIgnore_InputMode);
}
if (foregroundTex) {
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 123792d..3f60b4a 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -356,7 +356,11 @@
info.calcWithInitialValues(sk_sp_address_as_pointer_address(series), cnt,
0x0, kNone_GrColorComponentFlags, false, false);
if (kRGBA_GrColorComponentFlags == info.validFlags()) {
- return GrConstColorProcessor::Make(info.color(), GrConstColorProcessor::kIgnore_InputMode);
+ // TODO: We need to preserve 4f and color spaces during invariant processing. This color
+ // has definitely lost precision, and could easily be in the wrong gamut (or have been
+ // built from colors in multiple spaces).
+ return GrConstColorProcessor::Make(GrColor4f::FromGrColor(info.color()),
+ GrConstColorProcessor::kIgnore_InputMode);
}
SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
@@ -364,8 +368,10 @@
int firstIdx = info.firstEffectiveProcessorIndex();
cnt -= firstIdx;
if (firstIdx > 0 && info.inputColorIsUsed()) {
+ // See comment above - need to preserve 4f and color spaces during invariant processing.
sk_sp<GrFragmentProcessor> colorFP(GrConstColorProcessor::Make(
- info.inputColorToFirstEffectiveProccesor(), GrConstColorProcessor::kIgnore_InputMode));
+ GrColor4f::FromGrColor(info.inputColorToFirstEffectiveProccesor()),
+ GrConstColorProcessor::kIgnore_InputMode));
cnt += 1;
replacementSeries.reserve(cnt);
replacementSeries.emplace_back(std::move(colorFP));
diff --git a/src/gpu/GrPaint.cpp b/src/gpu/GrPaint.cpp
index d33881c..c6d7f7d 100644
--- a/src/gpu/GrPaint.cpp
+++ b/src/gpu/GrPaint.cpp
@@ -17,7 +17,7 @@
, fDisableOutputConversionToSRGB(false)
, fAllowSRGBInputs(false)
, fUsesDistanceVectorField(false)
- , fColor(GrColor4f::FromGrColor(GrColor_WHITE)) {}
+ , fColor(GrColor4f::OpaqueWhite()) {}
void GrPaint::setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) {
fXPFactory = GrCoverageSetOpXPFactory::Make(regionOp, invertCoverage);
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 1500878..ed974a7 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -636,8 +636,11 @@
// We can ignore origColor here - alpha is unchanged by gamma
GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
if (GrColor_WHITE != paintAlpha) {
+ // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
+ // color channels. It's value should be treated as the same in ANY color space.
grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
- paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode));
+ GrColor4f::FromGrColor(paintAlpha),
+ GrConstColorProcessor::kModulateRGBA_InputMode));
}
} else {
// The shader's FP sees the paint unpremul color
@@ -648,10 +651,9 @@
if (primColorMode) {
// There is a blend between the primitive color and the paint color. The blend considers
// the opaque paint color. The paint's alpha is applied to the post-blended color.
- // SRGBTODO: Preserve 4f on this code path
sk_sp<GrFragmentProcessor> processor(
- GrConstColorProcessor::Make(origColor.opaque().toGrColor(),
- GrConstColorProcessor::kIgnore_InputMode));
+ GrConstColorProcessor::Make(origColor.opaque(),
+ GrConstColorProcessor::kIgnore_InputMode));
if (primitiveIsSrc) {
processor = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(processor),
*primColorMode);
@@ -668,8 +670,11 @@
// We can ignore origColor here - alpha is unchanged by gamma
GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
if (GrColor_WHITE != paintAlpha) {
+ // No gamut conversion - paintAlpha is a (linear) alpha value, splatted to all
+ // color channels. It's value should be treated as the same in ANY color space.
grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
- paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode));
+ GrColor4f::FromGrColor(paintAlpha),
+ GrConstColorProcessor::kModulateRGBA_InputMode));
}
} else {
// No shader, no primitive color.
@@ -691,7 +696,8 @@
colorFilter->filterColor(skPaint.getColor()), false, nullptr));
}
} else {
- sk_sp<GrFragmentProcessor> cfFP(colorFilter->asFragmentProcessor(context));
+ sk_sp<GrFragmentProcessor> cfFP(colorFilter->asFragmentProcessor(context,
+ dc->getColorSpace()));
if (cfFP) {
grPaint->addColorFragmentProcessor(std::move(cfFP));
} else {
diff --git a/src/gpu/effects/GrConstColorProcessor.cpp b/src/gpu/effects/GrConstColorProcessor.cpp
index 0684c9c..019d699 100644
--- a/src/gpu/effects/GrConstColorProcessor.cpp
+++ b/src/gpu/effects/GrConstColorProcessor.cpp
@@ -14,7 +14,7 @@
class GLConstColorProcessor : public GrGLSLFragmentProcessor {
public:
- GLConstColorProcessor() : fPrevColor(GrColor_ILLEGAL) {}
+ GLConstColorProcessor() : fPrevColor(GrColor4f::kIllegalConstructor) {}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
@@ -44,26 +44,18 @@
protected:
void onSetData(const GrGLSLProgramDataManager& pdm, const GrProcessor& processor) override {
- GrColor color = processor.cast<GrConstColorProcessor>().color();
- // We use the "illegal" color value as an uninit sentinel. However, ut isn't inherently
- // illegal to use this processor with unpremul colors. So we correctly handle the case
- // when the "illegal" color is used but we will always upload it.
- if (GrColor_ILLEGAL == color || fPrevColor != color) {
- static const float scale = 1.f / 255.f;
- float floatColor[4] = {
- GrColorUnpackR(color) * scale,
- GrColorUnpackG(color) * scale,
- GrColorUnpackB(color) * scale,
- GrColorUnpackA(color) * scale,
- };
- pdm.set4fv(fColorUniform, 1, floatColor);
+ GrColor4f color = processor.cast<GrConstColorProcessor>().color();
+ // We use the "illegal" color value as an uninit sentinel. With GrColor4f, the "illegal"
+ // color is *really* illegal (not just unpremultiplied), so this check is simple.
+ if (fPrevColor != color) {
+ pdm.set4fv(fColorUniform, 1, color.fRGBA);
fPrevColor = color;
}
}
private:
GrGLSLProgramDataManager::UniformHandle fColorUniform;
- GrColor fPrevColor;
+ GrColor4f fPrevColor;
typedef GrGLSLFragmentProcessor INHERITED;
};
@@ -72,23 +64,23 @@
void GrConstColorProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) const {
if (kIgnore_InputMode == fMode) {
- inout->setToOther(kRGBA_GrColorComponentFlags, fColor,
+ inout->setToOther(kRGBA_GrColorComponentFlags, fColor.toGrColor(),
GrInvariantOutput::kWillNot_ReadInput);
} else {
- GrColor r = GrColorUnpackR(fColor);
- bool colorIsSingleChannel = r == GrColorUnpackG(fColor) && r == GrColorUnpackB(fColor) &&
- r == GrColorUnpackA(fColor);
+ float r = fColor.fRGBA[0];
+ bool colorIsSingleChannel = r == fColor.fRGBA[1] && r == fColor.fRGBA[2] &&
+ r == fColor.fRGBA[3];
if (kModulateRGBA_InputMode == fMode) {
if (colorIsSingleChannel) {
- inout->mulByKnownSingleComponent(r);
+ inout->mulByKnownSingleComponent(SkToU8(sk_float_round2int(255.0f * r)));
} else {
- inout->mulByKnownFourComponents(fColor);
+ inout->mulByKnownFourComponents(fColor.toGrColor());
}
} else {
if (colorIsSingleChannel) {
- inout->mulAlphaByKnownSingleComponent(r);
+ inout->mulAlphaByKnownSingleComponent(SkToU8(sk_float_round2int(255.0f * r)));
} else {
- inout->mulAlphaByKnownFourComponents(fColor);
+ inout->mulAlphaByKnownFourComponents(fColor.toGrColor());
}
}
}
@@ -113,7 +105,7 @@
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConstColorProcessor);
sk_sp<GrFragmentProcessor> GrConstColorProcessor::TestCreate(GrProcessorTestData* d) {
- GrColor color SK_INIT_TO_AVOID_WARNING;
+ GrColor4f color;
int colorPicker = d->fRandom->nextULessThan(3);
switch (colorPicker) {
case 0: {
@@ -121,15 +113,15 @@
uint32_t r = d->fRandom->nextULessThan(a+1);
uint32_t g = d->fRandom->nextULessThan(a+1);
uint32_t b = d->fRandom->nextULessThan(a+1);
- color = GrColorPackRGBA(r, g, b, a);
+ color = GrColor4f::FromGrColor(GrColorPackRGBA(r, g, b, a));
break;
}
case 1:
- color = 0;
+ color = GrColor4f::TransparentBlack();
break;
case 2:
- color = d->fRandom->nextULessThan(0x100);
- color = color | (color << 8) | (color << 16) | (color << 24);
+ uint32_t c = d->fRandom->nextULessThan(0x100);
+ color = GrColor4f::FromGrColor(c | (c << 8) | (c << 16) | (c << 24));
break;
}
InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt));
diff --git a/src/gpu/effects/GrConvexPolyEffect.cpp b/src/gpu/effects/GrConvexPolyEffect.cpp
index 5ce7867..7ad2c08 100644
--- a/src/gpu/effects/GrConvexPolyEffect.cpp
+++ b/src/gpu/effects/GrConvexPolyEffect.cpp
@@ -253,10 +253,11 @@
// skip the draw or omit the clip element.
if (!SkPathPriv::CheapComputeFirstDirection(path, &dir)) {
if (GrProcessorEdgeTypeIsInverseFill(type)) {
- return GrConstColorProcessor::Make(0xFFFFFFFF,
+ return GrConstColorProcessor::Make(GrColor4f::OpaqueWhite(),
GrConstColorProcessor::kModulateRGBA_InputMode);
}
- return GrConstColorProcessor::Make(0, GrConstColorProcessor::kIgnore_InputMode);
+ return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
+ GrConstColorProcessor::kIgnore_InputMode);
}
SkVector t;
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index fba4050..935747b 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -123,7 +123,7 @@
sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) {
switch (mode) {
case SkXfermode::kClear_Mode:
- return GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK,
+ return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode);
case SkXfermode::kSrc_Mode:
return src;
@@ -285,7 +285,7 @@
sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) {
switch (mode) {
case SkXfermode::kClear_Mode:
- return GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK,
+ return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode);
case SkXfermode::kSrc_Mode:
return nullptr;
@@ -300,7 +300,7 @@
sk_sp<GrFragmentProcessor> src, SkXfermode::Mode mode) {
switch (mode) {
case SkXfermode::kClear_Mode:
- return GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK,
+ return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode);
case SkXfermode::kDst_Mode:
return nullptr;
diff --git a/tests/GpuColorFilterTest.cpp b/tests/GpuColorFilterTest.cpp
index 0fbce6c56..723e9e9 100644
--- a/tests/GpuColorFilterTest.cpp
+++ b/tests/GpuColorFilterTest.cpp
@@ -99,7 +99,8 @@
for (size_t i = 0; i < SK_ARRAY_COUNT(filterTests); ++i) {
const GetConstantComponentTestCase& test = filterTests[i];
auto cf(SkColorFilter::MakeModeFilter(test.filterColor, test.filterMode));
- sk_sp<GrFragmentProcessor> fp(cf->asFragmentProcessor(ctxInfo.grContext()));
+ // TODO: Test other color spaces
+ sk_sp<GrFragmentProcessor> fp(cf->asFragmentProcessor(ctxInfo.grContext(), nullptr));
REPORTER_ASSERT(reporter, fp);
GrInvariantOutput inout(test.inputColor,
static_cast<GrColorComponentFlags>(test.inputComponents),