1bf87730c7da80616f6ea17765290dbd2c147a669bsalomon/*
2bf87730c7da80616f6ea17765290dbd2c147a669bsalomon* Copyright 2015 Google Inc.
3bf87730c7da80616f6ea17765290dbd2c147a669bsalomon*
4bf87730c7da80616f6ea17765290dbd2c147a669bsalomon* Use of this source code is governed by a BSD-style license that can be
5bf87730c7da80616f6ea17765290dbd2c147a669bsalomon* found in the LICENSE file.
6bf87730c7da80616f6ea17765290dbd2c147a669bsalomon*/
7bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
8bf87730c7da80616f6ea17765290dbd2c147a669bsalomon#include "GrFragmentProcessor.h"
9bf87730c7da80616f6ea17765290dbd2c147a669bsalomon#include "GrCoordTransform.h"
10a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon#include "GrPipeline.h"
11c0b642ca48d58416409e555549434066f09692b7Brian Salomon#include "GrPipelineAnalysis.h"
12c0b642ca48d58416409e555549434066f09692b7Brian Salomon#include "effects/GrConstColorProcessor.h"
13c0b642ca48d58416409e555549434066f09692b7Brian Salomon#include "effects/GrXfermodeFragmentProcessor.h"
1464c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLFragmentProcessor.h"
152d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h"
16018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h"
177ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h"
18bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
19bf87730c7da80616f6ea17765290dbd2c147a669bsalomonGrFragmentProcessor::~GrFragmentProcessor() {
20bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    // If we got here then our ref count must have reached zero, so we will have converted refs
21bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    // to pending executions for all children.
22bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    for (int i = 0; i < fChildProcessors.count(); ++i) {
23bf87730c7da80616f6ea17765290dbd2c147a669bsalomon        fChildProcessors[i]->completedExecution();
24bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
25bf87730c7da80616f6ea17765290dbd2c147a669bsalomon}
26bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
277312ff87f64f31d741989a60d993bcaa4bb20523bsalomonbool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const {
28bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    if (this->classID() != that.classID() ||
29f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        !this->hasSameSamplersAndAccesses(that)) {
30bf87730c7da80616f6ea17765290dbd2c147a669bsalomon        return false;
31bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
327312ff87f64f31d741989a60d993bcaa4bb20523bsalomon    if (!this->hasSameTransforms(that)) {
33bf87730c7da80616f6ea17765290dbd2c147a669bsalomon        return false;
34bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
35bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    if (!this->onIsEqual(that)) {
36bf87730c7da80616f6ea17765290dbd2c147a669bsalomon        return false;
37bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
38bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    if (this->numChildProcessors() != that.numChildProcessors()) {
39bf87730c7da80616f6ea17765290dbd2c147a669bsalomon        return false;
40bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
41bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    for (int i = 0; i < this->numChildProcessors(); ++i) {
427312ff87f64f31d741989a60d993bcaa4bb20523bsalomon        if (!this->childProcessor(i).isEqual(that.childProcessor(i))) {
43bf87730c7da80616f6ea17765290dbd2c147a669bsalomon            return false;
44bf87730c7da80616f6ea17765290dbd2c147a669bsalomon        }
45bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
46bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    return true;
47bf87730c7da80616f6ea17765290dbd2c147a669bsalomon}
48bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
4957d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const {
5057d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel    GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance();
51bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
52bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    for (int i = 0; i < fChildProcessors.count(); ++i) {
5357d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel        glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLSLInstance();
54bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
55bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    return glFragProc;
56bf87730c7da80616f6ea17765290dbd2c147a669bsalomon}
57bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
58bf87730c7da80616f6ea17765290dbd2c147a669bsalomonvoid GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
59bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    fCoordTransforms.push_back(transform);
60587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon    fFlags |= kUsesLocalCoords_Flag;
61bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    SkDEBUGCODE(transform->setInProcessor();)
62bf87730c7da80616f6ea17765290dbd2c147a669bsalomon}
63bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
6406ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemanint GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
6587332103c605dc3e0f76c0d1250a76c4ff71fddccdalton    this->combineRequiredFeatures(*child);
66bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
67bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    if (child->usesLocalCoords()) {
68587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        fFlags |= kUsesLocalCoords_Flag;
69bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
709b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck    if (child->usesDistanceVectorField()) {
71587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        fFlags |= kUsesDistanceVectorField_Flag;
729b03e7b29d963ea333a66dc5353e94f6391eb899dvonbeck    }
73bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
7406ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    int index = fChildProcessors.count();
7506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    fChildProcessors.push_back(child.release());
7606ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman
77bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    return index;
78bf87730c7da80616f6ea17765290dbd2c147a669bsalomon}
79bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
80bf87730c7da80616f6ea17765290dbd2c147a669bsalomonvoid GrFragmentProcessor::notifyRefCntIsZero() const {
81bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    // See comment above GrProgramElement for a detailed explanation of why we do this.
82bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    for (int i = 0; i < fChildProcessors.count(); ++i) {
83bf87730c7da80616f6ea17765290dbd2c147a669bsalomon        fChildProcessors[i]->addPendingExecution();
84bf87730c7da80616f6ea17765290dbd2c147a669bsalomon        fChildProcessors[i]->unref();
85bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
86bf87730c7da80616f6ea17765290dbd2c147a669bsalomon}
87bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
88bf87730c7da80616f6ea17765290dbd2c147a669bsalomonbool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
89a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    if (this->numCoordTransforms() != that.numCoordTransforms()) {
90bf87730c7da80616f6ea17765290dbd2c147a669bsalomon        return false;
91bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
92a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    int count = this->numCoordTransforms();
93bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    for (int i = 0; i < count; ++i) {
9467c18d6b5188a0497f6912a73d964c763d2f8f84Robert Phillips        if (!this->coordTransform(i).hasSameEffectAs(that.coordTransform(i))) {
95bf87730c7da80616f6ea17765290dbd2c147a669bsalomon            return false;
96bf87730c7da80616f6ea17765290dbd2c147a669bsalomon        }
97bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    }
98bf87730c7da80616f6ea17765290dbd2c147a669bsalomon    return true;
99bf87730c7da80616f6ea17765290dbd2c147a669bsalomon}
100bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
10106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemansk_sp<GrFragmentProcessor> GrFragmentProcessor::MulOutputByInputAlpha(
10206ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    sk_sp<GrFragmentProcessor> fp) {
103f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    if (!fp) {
104f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        return nullptr;
105f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    }
1067d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed    return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(fp), SkBlendMode::kDstIn);
107bf87730c7da80616f6ea17765290dbd2c147a669bsalomon}
108bf87730c7da80616f6ea17765290dbd2c147a669bsalomon
109de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osmannamespace {
110de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
111de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osmanclass PremulInputFragmentProcessor : public GrFragmentProcessor {
112de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osmanpublic:
113de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    PremulInputFragmentProcessor()
114de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman            : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
115de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                        kConstantOutputForConstantInput_OptimizationFlag) {
116de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        this->initClassID<PremulInputFragmentProcessor>();
117de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    }
118c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck
119de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    const char* name() const override { return "PremultiplyInput"; }
120de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
121de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osmanprivate:
122de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
123de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        class GLFP : public GrGLSLFragmentProcessor {
124de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        public:
125de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman            void emitCode(EmitArgs& args) override {
126de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
127de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
128de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
129de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                fragBuilder->codeAppendf("%s.rgb *= %s.a;",
130de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                                            args.fOutputColor, args.fInputColor);
131de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman            }
132de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        };
133de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        return new GLFP;
134de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    }
135c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck
136de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
137de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
138de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
139c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck
140de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
141de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        return input.premul();
142de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    }
143c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck
144de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    typedef GrFragmentProcessor INHERITED;
145de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman};
146c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck
147de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osmanclass UnpremulInputFragmentProcessor : public GrFragmentProcessor {
148de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osmanpublic:
149de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    UnpremulInputFragmentProcessor()
150de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman            : INHERITED(kPreservesOpaqueInput_OptimizationFlag |
151de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                        kConstantOutputForConstantInput_OptimizationFlag) {
152de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        this->initClassID<UnpremulInputFragmentProcessor>();
153de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    }
154de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
155de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    const char* name() const override { return "UnpremultiplyInput"; }
156de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
157de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osmanprivate:
158de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
159de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        class GLFP : public GrGLSLFragmentProcessor {
160de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        public:
161de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman            void emitCode(EmitArgs& args) override {
162de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
163de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
164de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, args.fInputColor);
165de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                fragBuilder->codeAppendf("float invAlpha = %s.a <= 0.0 ? 0.0 : 1.0 / %s.a;",
166de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                                         args.fInputColor, args.fInputColor);
167de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman                fragBuilder->codeAppendf("%s.rgb *= invAlpha;", args.fOutputColor);
168de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman            }
169de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        };
170de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        return new GLFP;
171de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    }
172de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
173de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
174de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
175de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
176de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
177de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
178de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        return input.unpremul();
179de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    }
180de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
181de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    typedef GrFragmentProcessor INHERITED;
182de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman};
183587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
184de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman}
185de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
186de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osmansk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulInput(sk_sp<GrFragmentProcessor> fp) {
187c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck    if (!fp) {
188c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck        return nullptr;
189c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck    }
190c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck    sk_sp<GrFragmentProcessor> fpPipeline[] = { sk_make_sp<PremulInputFragmentProcessor>(), fp};
191c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck    return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
192c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck}
193c526da94e4f2dc0c8521099dad2118c5d6b8da4advonbeck
194de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osmansk_sp<GrFragmentProcessor> GrFragmentProcessor::PremulOutput(sk_sp<GrFragmentProcessor> fp) {
195de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    if (!fp) {
196de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        return nullptr;
197de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    }
198de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<PremulInputFragmentProcessor>() };
199de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
200de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman}
201de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
202de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osmansk_sp<GrFragmentProcessor> GrFragmentProcessor::UnpremulOutput(sk_sp<GrFragmentProcessor> fp) {
203de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    if (!fp) {
204de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman        return nullptr;
205de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    }
206de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<UnpremulInputFragmentProcessor>() };
207de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman    return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
208de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman}
209de1a60534648ca8a6eb3ae32e06a7a9e9c0591f3Brian Osman
210ce425510a07632f14b7b779ec3864f719cb4326bBrian Osmansk_sp<GrFragmentProcessor> GrFragmentProcessor::SwizzleOutput(sk_sp<GrFragmentProcessor> fp,
211ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman                                                              const GrSwizzle& swizzle) {
212ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman    class SwizzleFragmentProcessor : public GrFragmentProcessor {
213ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman    public:
214ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        SwizzleFragmentProcessor(const GrSwizzle& swizzle)
215ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman                : INHERITED(kAll_OptimizationFlags)
216ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman                , fSwizzle(swizzle) {
217ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman            this->initClassID<SwizzleFragmentProcessor>();
218ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        }
219ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman
220ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        const char* name() const override { return "Swizzle"; }
221ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        const GrSwizzle& swizzle() const { return fSwizzle; }
222ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman
223ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman    private:
224ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
225ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman            class GLFP : public GrGLSLFragmentProcessor {
226ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman            public:
227ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman                void emitCode(EmitArgs& args) override {
228ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman                    const SwizzleFragmentProcessor& sfp = args.fFp.cast<SwizzleFragmentProcessor>();
229ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman                    const GrSwizzle& swizzle = sfp.swizzle();
230ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman                    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
231ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman
232ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman                    fragBuilder->codeAppendf("%s = %s.%s;",
233ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman                                             args.fOutputColor, args.fInputColor, swizzle.c_str());
234ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman                }
235ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman            };
236ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman            return new GLFP;
237ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        }
238ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman
239ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
240ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman            b->add32(fSwizzle.asKey());
241ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        }
242ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman
243ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        bool onIsEqual(const GrFragmentProcessor& other) const override {
244ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman            const SwizzleFragmentProcessor& sfp = other.cast<SwizzleFragmentProcessor>();
245ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman            return fSwizzle == sfp.fSwizzle;
246ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        }
247ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman
248ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
249ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman            return fSwizzle.applyTo(input);
250ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        }
251ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman
252ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        GrSwizzle fSwizzle;
253ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman
254ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        typedef GrFragmentProcessor INHERITED;
255ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman    };
256ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman
257ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman    if (!fp) {
258ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        return nullptr;
259ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman    }
260ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman    if (GrSwizzle::RGBA() == swizzle) {
261ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman        return fp;
262ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman    }
263ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman    sk_sp<GrFragmentProcessor> fpPipeline[] = { fp, sk_make_sp<SwizzleFragmentProcessor>(swizzle) };
264ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman    return GrFragmentProcessor::RunInSeries(fpPipeline, 2);
265ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman}
266ce425510a07632f14b7b779ec3864f719cb4326bBrian Osman
26722af73f2a5fd40fd9f991e35f7a216e924464cd4Brian Salomonsk_sp<GrFragmentProcessor> GrFragmentProcessor::MakeInputPremulAndMulByOutput(
26822af73f2a5fd40fd9f991e35f7a216e924464cd4Brian Salomon        sk_sp<GrFragmentProcessor> fp) {
269f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
270f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    class PremulFragmentProcessor : public GrFragmentProcessor {
271f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    public:
272587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        PremulFragmentProcessor(sk_sp<GrFragmentProcessor> processor)
273587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                : INHERITED(OptFlags(processor.get())) {
274f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            this->initClassID<PremulFragmentProcessor>();
275f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            this->registerChildProcessor(processor);
276f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        }
277f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
278f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        const char* name() const override { return "Premultiply"; }
279f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
280f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    private:
28157d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel        GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
28264c4728c70001ed074fecf5c4e083781987b12e9egdaniel            class GLFP : public GrGLSLFragmentProcessor {
283f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            public:
284f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                void emitCode(EmitArgs& args) override {
2858528541dd7f09f5bd76f3f1ce5f45d08ac7347c7cdalton                    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
286f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                    this->emitChild(0, nullptr, args);
2874ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                    fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
288f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                                                                args.fInputColor);
2894ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel                    fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
290f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                }
291f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            };
292f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            return new GLFP;
293f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        }
294f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
29594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon        void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
296f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
297f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
298f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
299587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        static OptimizationFlags OptFlags(const GrFragmentProcessor* inner) {
300587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            OptimizationFlags flags = kNone_OptimizationFlags;
301587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            if (inner->preservesOpaqueInput()) {
302587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                flags |= kPreservesOpaqueInput_OptimizationFlag;
303587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            }
304587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            if (inner->hasConstantOutputForConstantInput()) {
305587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                flags |= kConstantOutputForConstantInput_OptimizationFlag;
306587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            }
307587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            return flags;
308587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        }
309f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
310587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        GrColor4f constantOutputForConstantInput(GrColor4f input) const override {
311587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            GrColor4f childColor = ConstantOutputForConstantInput(this->childProcessor(0),
312587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                                                                  GrColor4f::OpaqueWhite());
313587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            return GrColor4f(input.fRGBA[3] * input.fRGBA[0] * childColor.fRGBA[0],
314587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                             input.fRGBA[3] * input.fRGBA[1] * childColor.fRGBA[1],
315587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                             input.fRGBA[3] * input.fRGBA[2] * childColor.fRGBA[2],
316587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                             input.fRGBA[3] * childColor.fRGBA[3]);
317587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        }
318587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
319587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        typedef GrFragmentProcessor INHERITED;
320f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    };
321f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    if (!fp) {
322f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        return nullptr;
323f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    }
32406ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    return sk_sp<GrFragmentProcessor>(new PremulFragmentProcessor(std::move(fp)));
325f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon}
326f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
327f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon//////////////////////////////////////////////////////////////////////////////
328f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
32906ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemansk_sp<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(sk_sp<GrFragmentProcessor> fp,
3304cea3b9e9d9836c926a8feb55d050993d40b4b5ebrianosman                                                              GrColor4f color) {
331f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
332f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    public:
3334cea3b9e9d9836c926a8feb55d050993d40b4b5ebrianosman        ReplaceInputFragmentProcessor(sk_sp<GrFragmentProcessor> child, GrColor4f color)
334587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                : INHERITED(OptFlags(child.get(), color)), fColor(color) {
335f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            this->initClassID<ReplaceInputFragmentProcessor>();
33606ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman            this->registerChildProcessor(std::move(child));
337f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        }
338f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
339f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        const char* name() const override { return "Replace Color"; }
340f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
34157d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel        GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
34264c4728c70001ed074fecf5c4e083781987b12e9egdaniel            class GLFP : public GrGLSLFragmentProcessor {
343f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            public:
344f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                GLFP() : fHaveSetColor(false) {}
345f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                void emitCode(EmitArgs& args) override {
346f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                    const char* colorName;
3475e58ceea8569f0d90ff7e3daf5de2def50407212cdalton                    fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
3485e58ceea8569f0d90ff7e3daf5de2def50407212cdalton                                                                 kVec4f_GrSLType,
3495e58ceea8569f0d90ff7e3daf5de2def50407212cdalton                                                                 kDefault_GrSLPrecision,
3505e58ceea8569f0d90ff7e3daf5de2def50407212cdalton                                                                 "Color", &colorName);
351f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                    this->emitChild(0, colorName, args);
352f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                }
353f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
354f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            private:
355018fb62d12d1febf121fe265da5b6117b86a6541egdaniel                void onSetData(const GrGLSLProgramDataManager& pdman,
356f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                               const GrProcessor& fp) override {
3574cea3b9e9d9836c926a8feb55d050993d40b4b5ebrianosman                    GrColor4f color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
358f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                    if (!fHaveSetColor || color != fPreviousColor) {
3594cea3b9e9d9836c926a8feb55d050993d40b4b5ebrianosman                        pdman.set4fv(fColorUni, 1, color.fRGBA);
360f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                        fPreviousColor = color;
361f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                        fHaveSetColor = true;
362f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                    }
363f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon                }
364f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
365018fb62d12d1febf121fe265da5b6117b86a6541egdaniel                GrGLSLProgramDataManager::UniformHandle fColorUni;
3664cea3b9e9d9836c926a8feb55d050993d40b4b5ebrianosman                bool      fHaveSetColor;
3674cea3b9e9d9836c926a8feb55d050993d40b4b5ebrianosman                GrColor4f fPreviousColor;
368f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            };
369f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
370f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            return new GLFP;
371f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        }
372f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
373f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    private:
374587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        static OptimizationFlags OptFlags(const GrFragmentProcessor* child, GrColor4f color) {
375587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            OptimizationFlags childFlags = child->optimizationFlags();
376587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            OptimizationFlags flags = kNone_OptimizationFlags;
377587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            if (childFlags & kConstantOutputForConstantInput_OptimizationFlag) {
378587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                flags |= kConstantOutputForConstantInput_OptimizationFlag;
379587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            }
380587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            if ((childFlags & kPreservesOpaqueInput_OptimizationFlag) && color.isOpaque()) {
381587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                flags |= kPreservesOpaqueInput_OptimizationFlag;
382587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            }
383587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            return flags;
384587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        }
385587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
38694efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon        void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override
38757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel        {}
388f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
389f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        bool onIsEqual(const GrFragmentProcessor& that) const override {
390f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon            return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
391f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon        }
392f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
393587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        GrColor4f constantOutputForConstantInput(GrColor4f) const override {
394587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            return ConstantOutputForConstantInput(this->childProcessor(0), fColor);
395587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        }
396587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
3974cea3b9e9d9836c926a8feb55d050993d40b4b5ebrianosman        GrColor4f fColor;
398587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
399587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        typedef GrFragmentProcessor INHERITED;
400f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon    };
401f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon
4025f13fbac19ee0ea9a3d5216740912d377a30d622Brian Salomon    return sk_sp<GrFragmentProcessor>(new ReplaceInputFragmentProcessor(std::move(fp), color));
403f1b7a1d82860e106ed7d3e0e876419e65783fb84bsalomon}
404e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon
40506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungemansk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProcessor>* series,
406e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon                                                            int cnt) {
407e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon    class SeriesFragmentProcessor : public GrFragmentProcessor {
408e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon    public:
409587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        SeriesFragmentProcessor(sk_sp<GrFragmentProcessor>* children, int cnt)
410587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                : INHERITED(OptFlags(children, cnt)) {
411e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon            SkASSERT(cnt > 1);
412e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon            this->initClassID<SeriesFragmentProcessor>();
413e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon            for (int i = 0; i < cnt; ++i) {
41406ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman                this->registerChildProcessor(std::move(children[i]));
415e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon            }
416e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        }
417e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon
418e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        const char* name() const override { return "Series"; }
419e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon
42057d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel        GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
42164c4728c70001ed074fecf5c4e083781987b12e9egdaniel            class GLFP : public GrGLSLFragmentProcessor {
422e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon            public:
423e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon                void emitCode(EmitArgs& args) override {
424ca9eeab0eaa32fc8f61be9003fafc3fe1afe78e4dvonbeck                    // First guy's input might be nil.
425ca9eeab0eaa32fc8f61be9003fafc3fe1afe78e4dvonbeck                    SkString temp("out0");
426ca9eeab0eaa32fc8f61be9003fafc3fe1afe78e4dvonbeck                    this->emitChild(0, args.fInputColor, &temp, args);
427ca9eeab0eaa32fc8f61be9003fafc3fe1afe78e4dvonbeck                    SkString input = temp;
428ca9eeab0eaa32fc8f61be9003fafc3fe1afe78e4dvonbeck                    for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
429e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon                        temp.printf("out%d", i);
430e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon                        this->emitChild(i, input.c_str(), &temp, args);
431e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon                        input = temp;
432e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon                    }
433e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon                    // Last guy writes to our output variable.
434e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon                    this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
435e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon                }
436e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon            };
437e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon            return new GLFP;
438e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        }
439e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon    private:
440587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        static OptimizationFlags OptFlags(sk_sp<GrFragmentProcessor>* children, int cnt) {
441587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            OptimizationFlags flags = kAll_OptimizationFlags;
442587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            for (int i = 0; i < cnt && flags != kNone_OptimizationFlags; ++i) {
443587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                flags &= children[i]->optimizationFlags();
444587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            }
445587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            return flags;
446587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        }
44794efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon        void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
448e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon
449e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        bool onIsEqual(const GrFragmentProcessor&) const override { return true; }
450e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon
451587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        GrColor4f constantOutputForConstantInput(GrColor4f color) const override {
452587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            int childCnt = this->numChildProcessors();
453587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            for (int i = 0; i < childCnt; ++i) {
454587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon                color = ConstantOutputForConstantInput(this->childProcessor(i), color);
455587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            }
456587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon            return color;
457587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        }
458587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon
459587e08f361ee3e775a6bbc6dca761dbba82e422cBrian Salomon        typedef GrFragmentProcessor INHERITED;
460e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon    };
461e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon
462e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon    if (!cnt) {
463e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon        return nullptr;
464e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon    }
465eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon    if (1 == cnt) {
466eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon        return series[0];
467eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon    }
468e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon    // Run the through the series, do the invariant output processing, and look for eliminations.
469c0b642ca48d58416409e555549434066f09692b7Brian Salomon    GrColorFragmentProcessorAnalysis info;
4700831f1b5f112f4e95532695dd701676f734cde54Brian Salomon    info.analyzeProcessors(sk_sp_address_as_pointer_address(series), cnt);
47106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    SkTArray<sk_sp<GrFragmentProcessor>> replacementSeries;
472eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon    GrColor4f knownColor;
473eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon    int leadingFPsToEliminate = info.initialProcessorsToEliminate(&knownColor);
474eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon    if (leadingFPsToEliminate) {
475eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon        sk_sp<GrFragmentProcessor> colorFP(
476eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon                GrConstColorProcessor::Make(knownColor, GrConstColorProcessor::kIgnore_InputMode));
477eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon        if (leadingFPsToEliminate == cnt) {
478eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon            return colorFP;
479eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon        }
480eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon        cnt = cnt - leadingFPsToEliminate + 1;
48106ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        replacementSeries.reserve(cnt);
48206ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        replacementSeries.emplace_back(std::move(colorFP));
48306ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        for (int i = 0; i < cnt - 1; ++i) {
484eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon            replacementSeries.emplace_back(std::move(series[leadingFPsToEliminate + i]));
48506ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        }
48606ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman        series = replacementSeries.begin();
487e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon    }
48806ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
489e25eea4b36a488448fb730f4e3dc5a900b0e2892bsalomon}
490a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon
491a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon//////////////////////////////////////////////////////////////////////////////
492a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon
493a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomonGrFragmentProcessor::Iter::Iter(const GrPipeline& pipeline) {
494a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
495a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon        fFPStack.push_back(&pipeline.getFragmentProcessor(i));
496a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    }
497a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon}
498a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon
499a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomonconst GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
500a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    if (fFPStack.empty()) {
501a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon        return nullptr;
502a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    }
503a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    const GrFragmentProcessor* back = fFPStack.back();
504a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    fFPStack.pop_back();
505a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
506a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon        fFPStack.push_back(&back->childProcessor(i));
507a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    }
508a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon    return back;
509a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon}
510a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3bsalomon
511