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>
This commit is contained in:
Brian Osman 2016-10-25 10:51:28 -04:00 committed by Skia Commit-Bot
parent 18b61f9cb9
commit 618d304eb3
29 changed files with 128 additions and 83 deletions

View File

@ -1334,13 +1334,17 @@ sk_sp<GrFragmentProcessor> SkPerlinNoiseShader2::asFragmentProcessor(const AsFPA
if (0 == fNumOctaves) { if (0 == fNumOctaves) {
if (kFractalNoise_Type == fType) { if (kFractalNoise_Type == fType) {
// Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2) // 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( sk_sp<GrFragmentProcessor> inner(
GrConstColorProcessor::Make(0x80404040, GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
GrConstColorProcessor::kModulateRGBA_InputMode)); GrConstColorProcessor::kModulateRGBA_InputMode));
return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
} }
// Emit zero. // Emit zero.
return GrConstColorProcessor::Make(0x0, GrConstColorProcessor::kIgnore_InputMode); return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode);
} }
SkAutoTUnref<GrTexture> permutationsTexture( SkAutoTUnref<GrTexture> permutationsTexture(

View File

@ -103,7 +103,7 @@ protected:
&grPaint)); &grPaint));
GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m; GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m;
GrColor color = kColors[procColor]; GrColor4f color = GrColor4f::FromGrColor(kColors[procColor]);
sk_sp<GrFragmentProcessor> fp(GrConstColorProcessor::Make(color, mode)); sk_sp<GrFragmentProcessor> fp(GrConstColorProcessor::Make(color, mode));
grPaint.addColorFragmentProcessor(std::move(fp)); grPaint.addColorFragmentProcessor(std::move(fp));

View File

@ -16,6 +16,7 @@
class GrContext; class GrContext;
class GrFragmentProcessor; class GrFragmentProcessor;
class SkBitmap; class SkBitmap;
class SkColorSpace;
class SkRasterPipeline; class SkRasterPipeline;
/** /**
@ -144,7 +145,8 @@ public:
* *
* A null return indicates that the color filter isn't implemented for the GPU backend. * 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 #endif
bool affectsTransparentBlack() const { bool affectsTransparentBlack() const {

View File

@ -26,7 +26,7 @@ public:
uint32_t getFlags() const override; uint32_t getFlags() const override;
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override; sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif #endif
SK_TO_STRING_OVERRIDE() SK_TO_STRING_OVERRIDE()

View File

@ -25,7 +25,7 @@ public:
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override; void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override; sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif #endif
SK_TO_STRING_OVERRIDE() SK_TO_STRING_OVERRIDE()

View File

@ -29,7 +29,7 @@ public:
void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override; void filterSpan(const SkPMColor src[], int count, SkPMColor[]) const override;
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override; sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif #endif
SK_TO_STRING_OVERRIDE() SK_TO_STRING_OVERRIDE()

View File

@ -185,6 +185,24 @@ struct GrColor4f {
fRGBA[3] = a; 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) { static GrColor4f FromGrColor(GrColor color) {
GrColor4f result; GrColor4f result;
GrColorToRGBAFloat(color, result.fRGBA); GrColorToRGBAFloat(color, result.fRGBA);

View File

@ -26,7 +26,7 @@ public:
}; };
static const int kInputModeCnt = kLastInputMode + 1; 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)); return sk_sp<GrFragmentProcessor>(new GrConstColorProcessor(color, mode));
} }
@ -34,16 +34,16 @@ public:
SkString dumpInfo() const override { SkString dumpInfo() const override {
SkString str; SkString str;
str.appendf("Color: 0x%08x", fColor); str.appendf("Color: 0x%08x", fColor.toGrColor());
return str; return str;
} }
GrColor color() const { return fColor; } GrColor4f color() const { return fColor; }
InputMode inputMode() const { return fMode; } InputMode inputMode() const { return fMode; }
private: private:
GrConstColorProcessor(GrColor color, InputMode mode) : fColor(color), fMode(mode) { GrConstColorProcessor(GrColor4f color, InputMode mode) : fColor(color), fMode(mode) {
this->initClassID<GrConstColorProcessor>(); this->initClassID<GrConstColorProcessor>();
} }
@ -57,7 +57,7 @@ private:
GR_DECLARE_FRAGMENT_PROCESSOR_TEST; GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
GrColor fColor; GrColor4f fColor;
InputMode fMode; InputMode fMode;
typedef GrFragmentProcessor INHERITED; typedef GrFragmentProcessor INHERITED;

View File

@ -32,7 +32,7 @@ bool SkColorFilter::asComponentTable(SkBitmap*) const {
} }
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*) const { sk_sp<GrFragmentProcessor> SkColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const {
return nullptr; return nullptr;
} }
#endif #endif
@ -114,9 +114,10 @@ public:
#endif #endif
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context) const override { sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext* context,
sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context)); SkColorSpace* dstColorSpace) const override {
sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context)); sk_sp<GrFragmentProcessor> innerFP(fInner->asFragmentProcessor(context, dstColorSpace));
sk_sp<GrFragmentProcessor> outerFP(fOuter->asFragmentProcessor(context, dstColorSpace));
if (!innerFP || !outerFP) { if (!innerFP || !outerFP) {
return nullptr; return nullptr;
} }

View File

@ -104,7 +104,8 @@ sk_sp<GrFragmentProcessor> SkColorFilterShader::asFragmentProcessor(const AsFPAr
return nullptr; return nullptr;
} }
sk_sp<GrFragmentProcessor> fp2(fFilter->asFragmentProcessor(args.fContext)); sk_sp<GrFragmentProcessor> fp2(fFilter->asFragmentProcessor(args.fContext,
args.fDstColorSpace));
if (!fp2) { if (!fp2) {
return fp1; return fp1;
} }

View File

@ -396,7 +396,8 @@ sk_sp<GrFragmentProcessor> ColorMatrixEffect::TestCreate(GrProcessorTestData* d)
return ColorMatrixEffect::Make(colorMatrix); return ColorMatrixEffect::Make(colorMatrix);
} }
sk_sp<GrFragmentProcessor> SkColorMatrixFilterRowMajor255::asFragmentProcessor(GrContext*) const { sk_sp<GrFragmentProcessor> SkColorMatrixFilterRowMajor255::asFragmentProcessor(
GrContext*, SkColorSpace*) const {
return ColorMatrixEffect::Make(fMatrix); return ColorMatrixEffect::Make(fMatrix);
} }

View File

@ -25,7 +25,7 @@ public:
sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter>) const override; sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter>) const override;
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override; sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif #endif
SK_TO_STRING_OVERRIDE() SK_TO_STRING_OVERRIDE()

View File

@ -89,8 +89,8 @@ SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
#include "SkGr.h" #include "SkGr.h"
#include "effects/GrConstColorProcessor.h" #include "effects/GrConstColorProcessor.h"
sk_sp<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const AsFPArgs&) const { sk_sp<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const AsFPArgs& args) const {
GrColor color = SkColorToPremulGrColor(fColor); GrColor4f color = SkColorToPremulGrColor4f(fColor, args.fDstColorSpace);
return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode); return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode);
} }
@ -208,10 +208,14 @@ SkShader::GradientType SkColor4Shader::asAGradient(GradientInfo* info) const {
#include "SkGr.h" #include "SkGr.h"
#include "effects/GrConstColorProcessor.h" #include "effects/GrConstColorProcessor.h"
sk_sp<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const AsFPArgs&) const { sk_sp<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const AsFPArgs& args) const {
// TODO: how to communicate color4f to Gr sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(),
GrColor color = SkColorToPremulGrColor(fCachedByteColor); args.fDstColorSpace);
return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode); GrColor4f color = GrColor4f::FromSkColor4f(fColor4);
if (colorSpaceXform) {
color = colorSpaceXform->apply(color);
}
return GrConstColorProcessor::Make(color.premul(), GrConstColorProcessor::kModulateA_InputMode);
} }
#endif #endif

View File

@ -192,7 +192,7 @@ sk_sp<GrFragmentProcessor> SkComposeShader::asFragmentProcessor(const AsFPArgs&
switch (mode) { switch (mode) {
case SkXfermode::kClear_Mode: case SkXfermode::kClear_Mode:
return GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK, return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode); GrConstColorProcessor::kIgnore_InputMode);
break; break;
case SkXfermode::kSrc_Mode: case SkXfermode::kSrc_Mode:

View File

@ -106,13 +106,14 @@ bool SkModeColorFilter::onAppendStages(SkRasterPipeline* p) const {
#include "effects/GrConstColorProcessor.h" #include "effects/GrConstColorProcessor.h"
#include "SkGr.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) { if (SkXfermode::kDst_Mode == fMode) {
return nullptr; return nullptr;
} }
sk_sp<GrFragmentProcessor> constFP( sk_sp<GrFragmentProcessor> constFP(
GrConstColorProcessor::Make(SkColorToPremulGrColor(fColor), GrConstColorProcessor::Make(SkColorToPremulGrColor4f(fColor, dstColorSpace),
GrConstColorProcessor::kIgnore_InputMode)); GrConstColorProcessor::kIgnore_InputMode));
sk_sp<GrFragmentProcessor> fp( sk_sp<GrFragmentProcessor> fp(
GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode)); GrXfermodeFragmentProcessor::MakeFromSrcProcessor(std::move(constFP), fMode));

View File

@ -32,7 +32,7 @@ public:
#endif #endif
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override; sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif #endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter) SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)

View File

@ -298,7 +298,8 @@ void GrColorCubeEffect::GLSLProcessor::GenKey(const GrProcessor& proc,
const GrGLSLCaps&, GrProcessorKeyBuilder* b) { 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(); static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key; GrUniqueKey key;
GrUniqueKey::Builder builder(&key, kDomain, 2); GrUniqueKey::Builder builder(&key, kDomain, 2);

View File

@ -50,7 +50,8 @@ void SkGammaColorFilter::toString(SkString* str) const {
#endif #endif
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> SkGammaColorFilter::asFragmentProcessor(GrContext*) const { sk_sp<GrFragmentProcessor> SkGammaColorFilter::asFragmentProcessor(GrContext*,
SkColorSpace*) const {
return GrGammaEffect::Make(fGamma); return GrGammaEffect::Make(fGamma);
} }
#endif #endif

View File

@ -111,7 +111,7 @@ private:
} }
}; };
sk_sp<GrFragmentProcessor> SkLumaColorFilter::asFragmentProcessor(GrContext*) const { sk_sp<GrFragmentProcessor> SkLumaColorFilter::asFragmentProcessor(GrContext*, SkColorSpace*) const {
return LumaColorFilterEffect::Make(); return LumaColorFilterEffect::Make();
} }
#endif #endif

View File

@ -906,13 +906,17 @@ sk_sp<GrFragmentProcessor> SkPerlinNoiseShader::asFragmentProcessor(const AsFPAr
if (0 == fNumOctaves) { if (0 == fNumOctaves) {
if (kFractalNoise_Type == fType) { if (kFractalNoise_Type == fType) {
// Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2) // 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( sk_sp<GrFragmentProcessor> inner(
GrConstColorProcessor::Make(0x80404040, GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
GrConstColorProcessor::kModulateRGBA_InputMode)); GrConstColorProcessor::kModulateRGBA_InputMode));
return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
} }
// Emit zero. // 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 // Either we don't stitch tiles, either we have a valid tile size

View File

@ -49,7 +49,7 @@ public:
sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter> inner) const override; sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter> inner) const override;
#if SK_SUPPORT_GPU #if SK_SUPPORT_GPU
sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*) const override; sk_sp<GrFragmentProcessor> asFragmentProcessor(GrContext*, SkColorSpace*) const override;
#endif #endif
void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override; void filterSpan(const SkPMColor src[], int count, SkPMColor dst[]) const override;
@ -561,13 +561,14 @@ sk_sp<GrFragmentProcessor> ColorTableEffect::TestCreate(GrProcessorTestData* d)
(flags & (1 << 2)) ? luts[2] : nullptr, (flags & (1 << 2)) ? luts[2] : nullptr,
(flags & (1 << 3)) ? luts[3] : nullptr (flags & (1 << 3)) ? luts[3] : nullptr
)); ));
sk_sp<SkColorSpace> colorSpace = GrTest::TestColorSpace(d->fRandom);
sk_sp<GrFragmentProcessor> fp = filter->asFragmentProcessor(d->fContext); sk_sp<GrFragmentProcessor> fp = filter->asFragmentProcessor(d->fContext, colorSpace.get());
SkASSERT(fp); SkASSERT(fp);
return fp; return fp;
} }
sk_sp<GrFragmentProcessor> SkTable_ColorFilter::asFragmentProcessor(GrContext* context) const { sk_sp<GrFragmentProcessor> SkTable_ColorFilter::asFragmentProcessor(GrContext* context,
SkColorSpace*) const {
SkBitmap bitmap; SkBitmap bitmap;
this->asComponentTable(&bitmap); this->asComponentTable(&bitmap);

View File

@ -268,7 +268,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU(
GrTextureDomain::kDecal_Mode, GrTextureDomain::kDecal_Mode,
GrTextureParams::kNone_FilterMode); GrTextureParams::kNone_FilterMode);
} else { } else {
bgFP = GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK, bgFP = GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode); GrConstColorProcessor::kIgnore_InputMode);
} }

View File

@ -356,7 +356,11 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProc
info.calcWithInitialValues(sk_sp_address_as_pointer_address(series), cnt, info.calcWithInitialValues(sk_sp_address_as_pointer_address(series), cnt,
0x0, kNone_GrColorComponentFlags, false, false); 0x0, kNone_GrColorComponentFlags, false, false);
if (kRGBA_GrColorComponentFlags == info.validFlags()) { 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; SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
@ -364,8 +368,10 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProc
int firstIdx = info.firstEffectiveProcessorIndex(); int firstIdx = info.firstEffectiveProcessorIndex();
cnt -= firstIdx; cnt -= firstIdx;
if (firstIdx > 0 && info.inputColorIsUsed()) { if (firstIdx > 0 && info.inputColorIsUsed()) {
// See comment above - need to preserve 4f and color spaces during invariant processing.
sk_sp<GrFragmentProcessor> colorFP(GrConstColorProcessor::Make( sk_sp<GrFragmentProcessor> colorFP(GrConstColorProcessor::Make(
info.inputColorToFirstEffectiveProccesor(), GrConstColorProcessor::kIgnore_InputMode)); GrColor4f::FromGrColor(info.inputColorToFirstEffectiveProccesor()),
GrConstColorProcessor::kIgnore_InputMode));
cnt += 1; cnt += 1;
replacementSeries.reserve(cnt); replacementSeries.reserve(cnt);
replacementSeries.emplace_back(std::move(colorFP)); replacementSeries.emplace_back(std::move(colorFP));

View File

@ -17,7 +17,7 @@ GrPaint::GrPaint()
, fDisableOutputConversionToSRGB(false) , fDisableOutputConversionToSRGB(false)
, fAllowSRGBInputs(false) , fAllowSRGBInputs(false)
, fUsesDistanceVectorField(false) , fUsesDistanceVectorField(false)
, fColor(GrColor4f::FromGrColor(GrColor_WHITE)) {} , fColor(GrColor4f::OpaqueWhite()) {}
void GrPaint::setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) { void GrPaint::setCoverageSetOpXPFactory(SkRegion::Op regionOp, bool invertCoverage) {
fXPFactory = GrCoverageSetOpXPFactory::Make(regionOp, invertCoverage); fXPFactory = GrCoverageSetOpXPFactory::Make(regionOp, invertCoverage);

View File

@ -636,8 +636,11 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context,
// We can ignore origColor here - alpha is unchanged by gamma // We can ignore origColor here - alpha is unchanged by gamma
GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor()); GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
if (GrColor_WHITE != paintAlpha) { 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( grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode)); GrColor4f::FromGrColor(paintAlpha),
GrConstColorProcessor::kModulateRGBA_InputMode));
} }
} else { } else {
// The shader's FP sees the paint unpremul color // The shader's FP sees the paint unpremul color
@ -648,9 +651,8 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context,
if (primColorMode) { if (primColorMode) {
// There is a blend between the primitive color and the paint color. The blend considers // 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. // 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( sk_sp<GrFragmentProcessor> processor(
GrConstColorProcessor::Make(origColor.opaque().toGrColor(), GrConstColorProcessor::Make(origColor.opaque(),
GrConstColorProcessor::kIgnore_InputMode)); GrConstColorProcessor::kIgnore_InputMode));
if (primitiveIsSrc) { if (primitiveIsSrc) {
processor = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(processor), processor = GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(processor),
@ -668,8 +670,11 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context,
// We can ignore origColor here - alpha is unchanged by gamma // We can ignore origColor here - alpha is unchanged by gamma
GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor()); GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor());
if (GrColor_WHITE != paintAlpha) { 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( grPaint->addColorFragmentProcessor(GrConstColorProcessor::Make(
paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode)); GrColor4f::FromGrColor(paintAlpha),
GrConstColorProcessor::kModulateRGBA_InputMode));
} }
} else { } else {
// No shader, no primitive color. // No shader, no primitive color.
@ -691,7 +696,8 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context,
colorFilter->filterColor(skPaint.getColor()), false, nullptr)); colorFilter->filterColor(skPaint.getColor()), false, nullptr));
} }
} else { } else {
sk_sp<GrFragmentProcessor> cfFP(colorFilter->asFragmentProcessor(context)); sk_sp<GrFragmentProcessor> cfFP(colorFilter->asFragmentProcessor(context,
dc->getColorSpace()));
if (cfFP) { if (cfFP) {
grPaint->addColorFragmentProcessor(std::move(cfFP)); grPaint->addColorFragmentProcessor(std::move(cfFP));
} else { } else {

View File

@ -14,7 +14,7 @@
class GLConstColorProcessor : public GrGLSLFragmentProcessor { class GLConstColorProcessor : public GrGLSLFragmentProcessor {
public: public:
GLConstColorProcessor() : fPrevColor(GrColor_ILLEGAL) {} GLConstColorProcessor() : fPrevColor(GrColor4f::kIllegalConstructor) {}
void emitCode(EmitArgs& args) override { void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
@ -44,26 +44,18 @@ public:
protected: protected:
void onSetData(const GrGLSLProgramDataManager& pdm, const GrProcessor& processor) override { void onSetData(const GrGLSLProgramDataManager& pdm, const GrProcessor& processor) override {
GrColor color = processor.cast<GrConstColorProcessor>().color(); GrColor4f color = processor.cast<GrConstColorProcessor>().color();
// We use the "illegal" color value as an uninit sentinel. However, ut isn't inherently // We use the "illegal" color value as an uninit sentinel. With GrColor4f, the "illegal"
// illegal to use this processor with unpremul colors. So we correctly handle the case // color is *really* illegal (not just unpremultiplied), so this check is simple.
// when the "illegal" color is used but we will always upload it. if (fPrevColor != color) {
if (GrColor_ILLEGAL == color || fPrevColor != color) { pdm.set4fv(fColorUniform, 1, color.fRGBA);
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);
fPrevColor = color; fPrevColor = color;
} }
} }
private: private:
GrGLSLProgramDataManager::UniformHandle fColorUniform; GrGLSLProgramDataManager::UniformHandle fColorUniform;
GrColor fPrevColor; GrColor4f fPrevColor;
typedef GrGLSLFragmentProcessor INHERITED; typedef GrGLSLFragmentProcessor INHERITED;
}; };
@ -72,23 +64,23 @@ private:
void GrConstColorProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) const { void GrConstColorProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) const {
if (kIgnore_InputMode == fMode) { if (kIgnore_InputMode == fMode) {
inout->setToOther(kRGBA_GrColorComponentFlags, fColor, inout->setToOther(kRGBA_GrColorComponentFlags, fColor.toGrColor(),
GrInvariantOutput::kWillNot_ReadInput); GrInvariantOutput::kWillNot_ReadInput);
} else { } else {
GrColor r = GrColorUnpackR(fColor); float r = fColor.fRGBA[0];
bool colorIsSingleChannel = r == GrColorUnpackG(fColor) && r == GrColorUnpackB(fColor) && bool colorIsSingleChannel = r == fColor.fRGBA[1] && r == fColor.fRGBA[2] &&
r == GrColorUnpackA(fColor); r == fColor.fRGBA[3];
if (kModulateRGBA_InputMode == fMode) { if (kModulateRGBA_InputMode == fMode) {
if (colorIsSingleChannel) { if (colorIsSingleChannel) {
inout->mulByKnownSingleComponent(r); inout->mulByKnownSingleComponent(SkToU8(sk_float_round2int(255.0f * r)));
} else { } else {
inout->mulByKnownFourComponents(fColor); inout->mulByKnownFourComponents(fColor.toGrColor());
} }
} else { } else {
if (colorIsSingleChannel) { if (colorIsSingleChannel) {
inout->mulAlphaByKnownSingleComponent(r); inout->mulAlphaByKnownSingleComponent(SkToU8(sk_float_round2int(255.0f * r)));
} else { } else {
inout->mulAlphaByKnownFourComponents(fColor); inout->mulAlphaByKnownFourComponents(fColor.toGrColor());
} }
} }
} }
@ -113,7 +105,7 @@ bool GrConstColorProcessor::onIsEqual(const GrFragmentProcessor& other) const {
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConstColorProcessor); GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConstColorProcessor);
sk_sp<GrFragmentProcessor> GrConstColorProcessor::TestCreate(GrProcessorTestData* d) { sk_sp<GrFragmentProcessor> GrConstColorProcessor::TestCreate(GrProcessorTestData* d) {
GrColor color SK_INIT_TO_AVOID_WARNING; GrColor4f color;
int colorPicker = d->fRandom->nextULessThan(3); int colorPicker = d->fRandom->nextULessThan(3);
switch (colorPicker) { switch (colorPicker) {
case 0: { case 0: {
@ -121,15 +113,15 @@ sk_sp<GrFragmentProcessor> GrConstColorProcessor::TestCreate(GrProcessorTestData
uint32_t r = d->fRandom->nextULessThan(a+1); uint32_t r = d->fRandom->nextULessThan(a+1);
uint32_t g = d->fRandom->nextULessThan(a+1); uint32_t g = d->fRandom->nextULessThan(a+1);
uint32_t b = 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; break;
} }
case 1: case 1:
color = 0; color = GrColor4f::TransparentBlack();
break; break;
case 2: case 2:
color = d->fRandom->nextULessThan(0x100); uint32_t c = d->fRandom->nextULessThan(0x100);
color = color | (color << 8) | (color << 16) | (color << 24); color = GrColor4f::FromGrColor(c | (c << 8) | (c << 16) | (c << 24));
break; break;
} }
InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt)); InputMode mode = static_cast<InputMode>(d->fRandom->nextULessThan(kInputModeCnt));

View File

@ -253,10 +253,11 @@ sk_sp<GrFragmentProcessor> GrConvexPolyEffect::Make(GrPrimitiveEdgeType type, co
// skip the draw or omit the clip element. // skip the draw or omit the clip element.
if (!SkPathPriv::CheapComputeFirstDirection(path, &dir)) { if (!SkPathPriv::CheapComputeFirstDirection(path, &dir)) {
if (GrProcessorEdgeTypeIsInverseFill(type)) { if (GrProcessorEdgeTypeIsInverseFill(type)) {
return GrConstColorProcessor::Make(0xFFFFFFFF, return GrConstColorProcessor::Make(GrColor4f::OpaqueWhite(),
GrConstColorProcessor::kModulateRGBA_InputMode); GrConstColorProcessor::kModulateRGBA_InputMode);
} }
return GrConstColorProcessor::Make(0, GrConstColorProcessor::kIgnore_InputMode); return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode);
} }
SkVector t; SkVector t;

View File

@ -123,7 +123,7 @@ sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromTwoProcessors(
sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) { sk_sp<GrFragmentProcessor> src, sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) {
switch (mode) { switch (mode) {
case SkXfermode::kClear_Mode: case SkXfermode::kClear_Mode:
return GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK, return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode); GrConstColorProcessor::kIgnore_InputMode);
case SkXfermode::kSrc_Mode: case SkXfermode::kSrc_Mode:
return src; return src;
@ -285,7 +285,7 @@ sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromDstProcessor(
sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) { sk_sp<GrFragmentProcessor> dst, SkXfermode::Mode mode) {
switch (mode) { switch (mode) {
case SkXfermode::kClear_Mode: case SkXfermode::kClear_Mode:
return GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK, return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode); GrConstColorProcessor::kIgnore_InputMode);
case SkXfermode::kSrc_Mode: case SkXfermode::kSrc_Mode:
return nullptr; return nullptr;
@ -300,7 +300,7 @@ sk_sp<GrFragmentProcessor> GrXfermodeFragmentProcessor::MakeFromSrcProcessor(
sk_sp<GrFragmentProcessor> src, SkXfermode::Mode mode) { sk_sp<GrFragmentProcessor> src, SkXfermode::Mode mode) {
switch (mode) { switch (mode) {
case SkXfermode::kClear_Mode: case SkXfermode::kClear_Mode:
return GrConstColorProcessor::Make(GrColor_TRANSPARENT_BLACK, return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
GrConstColorProcessor::kIgnore_InputMode); GrConstColorProcessor::kIgnore_InputMode);
case SkXfermode::kDst_Mode: case SkXfermode::kDst_Mode:
return nullptr; return nullptr;

View File

@ -99,7 +99,8 @@ DEF_GPUTEST_FOR_ALL_CONTEXTS(GpuColorFilter, reporter, ctxInfo) {
for (size_t i = 0; i < SK_ARRAY_COUNT(filterTests); ++i) { for (size_t i = 0; i < SK_ARRAY_COUNT(filterTests); ++i) {
const GetConstantComponentTestCase& test = filterTests[i]; const GetConstantComponentTestCase& test = filterTests[i];
auto cf(SkColorFilter::MakeModeFilter(test.filterColor, test.filterMode)); 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); REPORTER_ASSERT(reporter, fp);
GrInvariantOutput inout(test.inputColor, GrInvariantOutput inout(test.inputColor,
static_cast<GrColorComponentFlags>(test.inputComponents), static_cast<GrColorComponentFlags>(test.inputComponents),