1c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon/*
2c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon * Copyright 2015 Google Inc.
3c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon *
4c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon * Use of this source code is governed by a BSD-style license that can be
5c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon * found in the LICENSE file.
6c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon */
7c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
8c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon#include "effects/GrConstColorProcessor.h"
9c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon#include "gl/GrGLProcessor.h"
10c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon#include "gl/GrGLSL.h"
11c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon#include "gl/builders/GrGLProgramBuilder.h"
12c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
13c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomonclass GLConstColorProcessor : public GrGLFragmentProcessor {
14c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomonpublic:
15c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    GLConstColorProcessor() : fPrevColor(GrColor_ILLEGAL) {}
16c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
17c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    void emitCode(GrGLFPBuilder* builder,
18c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                  const GrFragmentProcessor& fp,
19c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                  const char* outputColor,
20c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                  const char* inputColor,
21c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                  const TransformedCoordsArray& coords,
22c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                  const TextureSamplerArray& samplers) override {
2329bee0fe657fabf7c396502b69c9167fba13eaaaegdaniel        GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
24c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        const char* colorUni;
25c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        fColorUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
26c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                                            kVec4f_GrSLType, kMedium_GrSLPrecision, "constantColor",
27c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                                            &colorUni);
28c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        switch (fp.cast<GrConstColorProcessor>().inputMode()) {
29c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            case GrConstColorProcessor::kIgnore_InputMode:
30c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                fsBuilder->codeAppendf("%s = %s;", outputColor, colorUni);
31c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                break;
32c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            case GrConstColorProcessor::kModulateRGBA_InputMode:
33c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                fsBuilder->codeAppendf("%s = %s * %s;", outputColor, inputColor, colorUni);
34c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                break;
35c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            case GrConstColorProcessor::kModulateA_InputMode:
36c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                fsBuilder->codeAppendf("%s = %s.a * %s;", outputColor, inputColor, colorUni);
37c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                break;
38c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        }
39c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    }
40c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
41c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    void setData(const GrGLProgramDataManager& pdm, const GrProcessor& processor) override {
42c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        GrColor color = processor.cast<GrConstColorProcessor>().color();
43c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        // We use the "illegal" color value as an uninit sentinel. However, ut isn't inherently
44c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        // illegal to use this processor with unpremul colors. So we correctly handle the case
45c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        // when the "illegal" color is used but we will always upload it.
46c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        if (GrColor_ILLEGAL == color || fPrevColor != color) {
47c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            static const GrGLfloat scale = 1.f / 255.f;
48c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            GrGLfloat floatColor[4] = {
49c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                GrColorUnpackR(color) * scale,
50c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                GrColorUnpackG(color) * scale,
51c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                GrColorUnpackB(color) * scale,
52c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                GrColorUnpackA(color) * scale,
53c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            };
54c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            pdm.set4fv(fColorUniform, 1, floatColor);
55c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            fPrevColor = color;
56c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        }
57c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    }
58c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
59c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomonprivate:
60c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    GrGLProgramDataManager::UniformHandle fColorUniform;
61c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    GrColor                               fPrevColor;
62c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
63c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    typedef GrGLFragmentProcessor INHERITED;
64c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon};
65c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
66c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon///////////////////////////////////////////////////////////////////////////////
67c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
68c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomonvoid GrConstColorProcessor::onComputeInvariantOutput(GrInvariantOutput* inout) const {
69c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    if (kIgnore_InputMode == fMode) {
70c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        inout->setToOther(kRGBA_GrColorComponentFlags, fColor, GrInvariantOutput::kWill_ReadInput);
71c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    } else {
72c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        GrColor r = GrColorUnpackR(fColor);
73c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        bool colorIsSingleChannel = r == GrColorUnpackG(fColor) && r == GrColorUnpackB(fColor) &&
74c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                                    r == GrColorUnpackA(fColor);
75c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        if (kModulateRGBA_InputMode == fMode) {
76c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            if (colorIsSingleChannel) {
77c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                inout->mulByKnownSingleComponent(r);
78c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            } else {
79c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                inout->mulByKnownFourComponents(fColor);
80c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            }
81c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        } else {
82c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            if (colorIsSingleChannel) {
83c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                inout->mulAlphaByKnownSingleComponent(r);
84c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            } else {
85c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                inout->mulAlphaByKnownFourComponents(fColor);
86c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            }
87c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        }
88c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    }
89c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon}
90c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
91cfc18867d982119d9dc2888bf09f1093012daaddjvanverthvoid GrConstColorProcessor::getGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder* b) const {
92c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    b->add32(fMode);
93c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon}
94c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
95c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomonGrGLFragmentProcessor* GrConstColorProcessor::createGLInstance() const  {
96c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    return SkNEW(GLConstColorProcessor);
97c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon}
98c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
99c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomonbool GrConstColorProcessor::onIsEqual(const GrFragmentProcessor& other) const {
100c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    const GrConstColorProcessor& that = other.cast<GrConstColorProcessor>();
101c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    return fMode == that.fMode && fColor == that.fColor;
102c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon}
103c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
104c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon///////////////////////////////////////////////////////////////////////////////
105c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
106c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomonGR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConstColorProcessor);
107c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon
108c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomonGrFragmentProcessor* GrConstColorProcessor::TestCreate(SkRandom* random,
109c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                                                       GrContext*,
110c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                                                       const GrDrawTargetCaps&,
111c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon                                                       GrTexture*[]) {
112c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    GrColor color;
113c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    int colorPicker = random->nextULessThan(3);
114c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    switch (colorPicker) {
115c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        case 0: {
116c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            uint32_t a = random->nextULessThan(0x100);
117c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            uint32_t r = random->nextULessThan(a+1);
118c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            uint32_t g = random->nextULessThan(a+1);
119c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            uint32_t b = random->nextULessThan(a+1);
120c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            color = GrColorPackRGBA(r, g, b, a);
121c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            break;
122c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        }
123c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        case 1:
124c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            color = 0;
125c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            break;
126c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon        case 2:
127c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            color = random->nextULessThan(0x100);
128c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            color = color | (color << 8) | (color << 16) | (color << 24);
129c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon            break;
130c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    }
131c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    InputMode mode = static_cast<InputMode>(random->nextULessThan(kInputModeCnt));
132c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon    return GrConstColorProcessor::Create(color, mode);
133c9c3e62b4ef6ec288549a0ad1d252986d7f0889dbsalomon}
134