aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/effects/GrConstColorProcessor.cpp
blob: a8b328e9b9f870aa6655d91d1d1f7d86027acda2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * 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/GrConstColorProcessor.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLUniformHandler.h"

class GLConstColorProcessor : public GrGLSLFragmentProcessor {
public:
    GLConstColorProcessor() : fPrevColor(GrColor4f::kIllegalConstructor) {}

    void emitCode(EmitArgs& args) override {
        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
        const char* colorUni;
        fColorUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
                                                         kVec4f_GrSLType, kMedium_GrSLPrecision,
                                                         "constantColor",
                                                         &colorUni);
        GrConstColorProcessor::InputMode mode = args.fFp.cast<GrConstColorProcessor>().inputMode();
        if (!args.fInputColor) {
            mode = GrConstColorProcessor::kIgnore_InputMode;
        }
        switch (mode) {
            case GrConstColorProcessor::kIgnore_InputMode:
                fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, colorUni);
                break;
            case GrConstColorProcessor::kModulateRGBA_InputMode:
                fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputColor, args.fInputColor,
                                       colorUni);
                break;
            case GrConstColorProcessor::kModulateA_InputMode:
                fragBuilder->codeAppendf("%s = %s.a * %s;", args.fOutputColor, args.fInputColor,
                                       colorUni);
                break;
        }
    }

protected:
    void onSetData(const GrGLSLProgramDataManager& pdm,
                   const GrFragmentProcessor& processor) override {
        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;
    GrColor4f                               fPrevColor;

    typedef GrGLSLFragmentProcessor INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::clone() const {
    return Make(fColor, fMode);
}

GrColor4f GrConstColorProcessor::constantOutputForConstantInput(GrColor4f input) const {
    switch (fMode) {
        case kIgnore_InputMode:
            return fColor;
        case kModulateA_InputMode:
            return fColor.mulByScalar(input.fRGBA[3]);
        case kModulateRGBA_InputMode:
            return fColor.modulate(input);
    }
    SK_ABORT("Unexpected mode");
    return GrColor4f::TransparentBlack();
}

void GrConstColorProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
                                                  GrProcessorKeyBuilder* b) const {
    b->add32(fMode);
}

GrGLSLFragmentProcessor* GrConstColorProcessor::onCreateGLSLInstance() const  {
    return new GLConstColorProcessor;
}

bool GrConstColorProcessor::onIsEqual(const GrFragmentProcessor& other) const {
    const GrConstColorProcessor& that = other.cast<GrConstColorProcessor>();
    return fMode == that.fMode && fColor == that.fColor;
}

///////////////////////////////////////////////////////////////////////////////

GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConstColorProcessor);

#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrConstColorProcessor::TestCreate(GrProcessorTestData* d) {
    GrColor4f color;
    int colorPicker = d->fRandom->nextULessThan(3);
    switch (colorPicker) {
        case 0: {
            uint32_t a = d->fRandom->nextULessThan(0x100);
            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 = GrColor4f::FromGrColor(GrColorPackRGBA(r, g, b, a));
            break;
        }
        case 1:
            color = GrColor4f::TransparentBlack();
            break;
        case 2:
            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));
    return GrConstColorProcessor::Make(color, mode);
}
#endif