| Index: src/gpu/effects/GrColorProcessor.cpp | 
| diff --git a/src/gpu/effects/GrColorProcessor.cpp b/src/gpu/effects/GrColorProcessor.cpp | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..d0f896427ba5529215fcc853c2e55e8e874a1320 | 
| --- /dev/null | 
| +++ b/src/gpu/effects/GrColorProcessor.cpp | 
| @@ -0,0 +1,109 @@ | 
| +/* | 
| + * 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 "effects/GrColorProcessor.h" | 
| +#include "gl/GrGLProcessor.h" | 
| +#include "gl/GrGLSL.h" | 
| +#include "gl/builders/GrGLProgramBuilder.h" | 
| + | 
| +class GrGLColorProcessor : public GrGLFragmentProcessor { | 
| +public: | 
| +    GrGLColorProcessor() : fPrevColor(GrColor_ILLEGAL) {} | 
| + | 
| +    void emitCode(GrGLFPBuilder* builder, | 
| +                  const GrFragmentProcessor& fp, | 
| +                  const char* outputColor, | 
| +                  const char* inputColor, | 
| +                  const TransformedCoordsArray& coords, | 
| +                  const TextureSamplerArray& samplers) SK_OVERRIDE { | 
| +        GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); | 
| +        const char* colorUni; | 
| +        fColorUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, | 
| +                                            kVec4f_GrSLType, kMedium_GrSLPrecision, "constantColor", | 
| +                                            &colorUni); | 
| +        switch (fp.cast<GrColorProcessor>().inputMode()) { | 
| +            case GrColorProcessor::kIgnore_InputMode: | 
| +                fsBuilder->codeAppendf("%s = %s;", outputColor, colorUni); | 
| +                break; | 
| +            case GrColorProcessor::kModulateRGBA_InputMode: | 
| +                fsBuilder->codeAppendf("%s = %s * %s;", outputColor, inputColor, colorUni); | 
| +                break; | 
| +            case GrColorProcessor::kModulateA_InputMode: | 
| +                fsBuilder->codeAppendf("%s = %s.a * %s;", outputColor, inputColor, colorUni); | 
| +                break; | 
| +        } | 
| +    } | 
| + | 
| +    void setData(const GrGLProgramDataManager& pdm, const GrProcessor& processor) SK_OVERRIDE { | 
| +        GrColor color = processor.cast<GrColorProcessor>().color(); | 
| +        // We use the value 0 as an uninit sentinel, so we will always upload that value even if it | 
| +        // were to be used repeatedly. | 
| +        if (GrColor_ILLEGAL == color || fPrevColor != color) { | 
| +            static const GrGLfloat scale = 1.f / 255.f; | 
| +            GrGLfloat floatColor[4] = { | 
| +                GrColorUnpackR(color) * scale, | 
| +                GrColorUnpackG(color) * scale, | 
| +                GrColorUnpackB(color) * scale, | 
| +                GrColorUnpackA(color) * scale, | 
| +            }; | 
| +            pdm.set4fv(fColorUniform, 1, floatColor); | 
| +            fPrevColor = color; | 
| +        } | 
| +    } | 
| + | 
| +private: | 
| +    GrGLProgramDataManager::UniformHandle fColorUniform; | 
| +    GrColor                               fPrevColor; | 
| + | 
| +    typedef GrGLFragmentProcessor INHERITED; | 
| +}; | 
| + | 
| +/////////////////////////////////////////////////////////////////////////////// | 
| + | 
| +void GrColorProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) const { | 
| +    if (kIgnore_InputMode == fMode) { | 
| +        inout->setToOther(kRGBA_GrColorComponentFlags, fColor, GrInvariantOutput::kWill_ReadInput); | 
| +    } else { | 
| +        GrColor r = GrColorUnpackR(fColor); | 
| +        bool colorIsSingleChannel = r == GrColorUnpackG(fColor) && r == GrColorUnpackB(fColor) && | 
| +                                    r == GrColorUnpackA(fColor); | 
| +        if (kIgnore_InputMode == fMode) { | 
| +            if (colorIsSingleChannel) { | 
| +                inout->mulByKnownSingleComponent(r); | 
| +            } else { | 
| +                inout->mulByKnownFourComponents(fColor); | 
| +            } | 
| +        } else { | 
| +            if (colorIsSingleChannel) { | 
| +                inout->mulAlphaByKnownSingleComponent(r); | 
| +            } else { | 
| +                inout->mulAlphaByKnownFourComponents(fColor); | 
| +            } | 
| +        } | 
| +    } | 
| +} | 
| + | 
| +void GrColorProcessor::getGLProcessorKey(const GrGLCaps&, GrProcessorKeyBuilder* b) const { | 
| +    b->add32(fMode); | 
| +} | 
| + | 
| +GrGLFragmentProcessor* GrColorProcessor::createGLInstance() const  { | 
| +    return SkNEW(GrGLColorProcessor); | 
| +} | 
| + | 
| +/////////////////////////////////////////////////////////////////////////////// | 
| + | 
| +GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrColorProcessor); | 
| + | 
| +GrFragmentProcessor* GrColorProcessor::TestCreate(SkRandom* random, | 
| +                                                  GrContext*, | 
| +                                                  const GrDrawTargetCaps&, | 
| +                                                  GrTexture*[]) { | 
| +    GrColor color = random->nextU(); | 
| +    InputMode mode = static_cast<InputMode>(random->nextULessThan(kInputModeCnt)); | 
| +    return GrColorProcessor::Create(color, mode); | 
| +} | 
|  |