GrProcessor.h revision 0e08fc17e4718f7ce4e38f793695896473e96948
1168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com/*
2168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com * Copyright 2012 Google Inc.
3168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com *
4168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com * Use of this source code is governed by a BSD-style license that can be
5168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com * found in the LICENSE file.
6168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com */
7168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com
8b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#ifndef GrProcessor_DEFINED
9b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#define GrProcessor_DEFINED
10168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com
11b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrBackendProcessorFactory.h"
12371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com#include "GrColor.h"
13b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessorUnitTest.h"
1495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#include "GrProgramElement.h"
15249af15fb82833d2274850c589812b6e69df0033joshualitt#include "GrShaderVar.h"
16047696c1c67b2e0a73f2b951ce23ff5b155111bbbsalomon@google.com#include "GrTextureAccess.h"
17ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org#include "GrTypesPriv.h"
18249af15fb82833d2274850c589812b6e69df0033joshualitt#include "SkString.h"
1907eecdca3e331eb4066c53a29305aeea6d692961tomhudson@google.com
20b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrBackendProcessorFactory;
21168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.comclass GrContext;
2277af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.comclass GrCoordTransform;
2395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
2450db75c871b203081a32190ab173f13c785a147fbsalomon@google.com/** Provides custom vertex shader, fragment shader, uniform data for a particular stage of the
2550db75c871b203081a32190ab173f13c785a147fbsalomon@google.com    Ganesh shading pipeline.
26289efe014ad7628de7cf2c5177a42cacd1e335adbsalomon@google.com    Subclasses must have a function that produces a human-readable name:
27289efe014ad7628de7cf2c5177a42cacd1e335adbsalomon@google.com        static const char* Name();
28b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrProcessor objects *must* be immutable: after being constructed, their fields may not change.
290ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
30b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    Dynamically allocated GrProcessors are managed by a per-thread memory pool. The ref count of an
3197b9ab72cd5ee0cba4692082737266376425f27cbsalomon    effect must reach 0 before the thread terminates and the pool is destroyed. To create a static
3297b9ab72cd5ee0cba4692082737266376425f27cbsalomon    effect use the macro GR_CREATE_STATIC_EFFECT declared below.
33289efe014ad7628de7cf2c5177a42cacd1e335adbsalomon@google.com  */
34b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrProcessor : public GrProgramElement {
35168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.compublic:
36b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    SK_DECLARE_INST_COUNT(GrProcessor)
3715e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
38b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual ~GrProcessor();
39168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com
401a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    struct InvariantOutput{
41ab84fae29fdee95987b10c00ff34957476a66263egdaniel        InvariantOutput() : fColor(0), fValidFlags(0), fIsSingleComponent(false),
42ab84fae29fdee95987b10c00ff34957476a66263egdaniel                            fNonMulStageFound(false) {}
43651713408c5a5d9565665967ad09981250c7a8c9joshualitt
44ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        void mulByUnknownOpaqueColor() {
45ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            if (this->isOpaque()) {
46ccb2e384a036f29d989d3c1468f879324e81a678egdaniel                fValidFlags = kA_GrColorComponentFlag;
47ccb2e384a036f29d989d3c1468f879324e81a678egdaniel                fIsSingleComponent = false;
48ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            } else {
49ccb2e384a036f29d989d3c1468f879324e81a678egdaniel                // Since the current state is not opaque we no longer care if the color being
50ccb2e384a036f29d989d3c1468f879324e81a678egdaniel                // multiplied is opaque.
51ccb2e384a036f29d989d3c1468f879324e81a678egdaniel                this->mulByUnknownColor();
52ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            }
53ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        }
54ccb2e384a036f29d989d3c1468f879324e81a678egdaniel
55ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        void mulByUnknownColor() {
56ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            if (this->hasZeroAlpha()) {
57ab84fae29fdee95987b10c00ff34957476a66263egdaniel                this->internalSetToTransparentBlack();
58ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            } else {
59ab84fae29fdee95987b10c00ff34957476a66263egdaniel                this->internalSetToUnknown();
60ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            }
61ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        }
62ccb2e384a036f29d989d3c1468f879324e81a678egdaniel
63ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        void mulByUnknownAlpha() {
64ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            if (this->hasZeroAlpha()) {
65ab84fae29fdee95987b10c00ff34957476a66263egdaniel                this->internalSetToTransparentBlack();
66ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            } else {
67ccb2e384a036f29d989d3c1468f879324e81a678egdaniel                // We don't need to change fIsSingleComponent in this case
68ccb2e384a036f29d989d3c1468f879324e81a678egdaniel                fValidFlags = 0;
69ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            }
70ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        }
71ccb2e384a036f29d989d3c1468f879324e81a678egdaniel
72ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        void invalidateComponents(uint8_t invalidateFlags) {
73ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            fValidFlags &= ~invalidateFlags;
74ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            fIsSingleComponent = false;
75ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        }
76ccb2e384a036f29d989d3c1468f879324e81a678egdaniel
77ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        void setToTransparentBlack() {
78ab84fae29fdee95987b10c00ff34957476a66263egdaniel            this->internalSetToTransparentBlack();
79ab84fae29fdee95987b10c00ff34957476a66263egdaniel            fNonMulStageFound = true;
80ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        }
81ccb2e384a036f29d989d3c1468f879324e81a678egdaniel
82ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        void setToOther(uint8_t validFlags, GrColor color) {
83ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            fValidFlags = validFlags;
84ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            fColor = color;
85ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            fIsSingleComponent = false;
86ab84fae29fdee95987b10c00ff34957476a66263egdaniel            fNonMulStageFound = true;
87ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        }
88ccb2e384a036f29d989d3c1468f879324e81a678egdaniel
89ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        void setToUnknown() {
90ab84fae29fdee95987b10c00ff34957476a66263egdaniel            this->internalSetToUnknown();
91ab84fae29fdee95987b10c00ff34957476a66263egdaniel            fNonMulStageFound= true;
92ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        }
93ccb2e384a036f29d989d3c1468f879324e81a678egdaniel
941a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel        bool isOpaque() const {
951a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel            return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUnpackA(fColor));
961a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel        }
971a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel
981a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel        bool isSolidWhite() const {
991a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel            return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF == fColor);
1001a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel        }
1011a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel
102ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        GrColor color() const { return fColor; }
103ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        uint8_t validFlags() const { return fValidFlags; }
104ccb2e384a036f29d989d3c1468f879324e81a678egdaniel
1051a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel        /**
1061a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel         * If isSingleComponent is true, then the flag values for r, g, b, and a must all be the
1071a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel         * same. If the flags are all set then all color components must be equal.
1081a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel         */
1091a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel        SkDEBUGCODE(void validate() const;)
1101a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel
1111a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    private:
112ab84fae29fdee95987b10c00ff34957476a66263egdaniel        void internalSetToTransparentBlack() {
113ab84fae29fdee95987b10c00ff34957476a66263egdaniel            fValidFlags = kRGBA_GrColorComponentFlags;
114ab84fae29fdee95987b10c00ff34957476a66263egdaniel            fColor = 0;
115ab84fae29fdee95987b10c00ff34957476a66263egdaniel            fIsSingleComponent = true;
116ab84fae29fdee95987b10c00ff34957476a66263egdaniel        }
117ab84fae29fdee95987b10c00ff34957476a66263egdaniel
118ab84fae29fdee95987b10c00ff34957476a66263egdaniel        void internalSetToUnknown() {
119ab84fae29fdee95987b10c00ff34957476a66263egdaniel            fValidFlags = 0;
120ab84fae29fdee95987b10c00ff34957476a66263egdaniel            fIsSingleComponent = false;
121ab84fae29fdee95987b10c00ff34957476a66263egdaniel        }
122ab84fae29fdee95987b10c00ff34957476a66263egdaniel
123ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        bool hasZeroAlpha() const {
124ccb2e384a036f29d989d3c1468f879324e81a678egdaniel            return ((fValidFlags & kA_GrColorComponentFlag) && 0 == GrColorUnpackA(fColor));
125ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        }
1261a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel
127ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        SkDEBUGCODE(bool colorComponentsAllEqual() const;)
1281a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel        /**
1291a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel         * If alpha is valid, check that any valid R,G,B values are <= A
1301a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel         */
1311a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel        SkDEBUGCODE(bool validPreMulColor() const;)
132ccb2e384a036f29d989d3c1468f879324e81a678egdaniel
133ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        // Friended class that have "controller" code which loop over stages calling
134ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        // computeInvarianteOutput(). These controllers may need to manually adjust the internal
135ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        // members of InvariantOutput
136ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        friend class GrDrawState;
137ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        friend class GrOptDrawState;
138ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        friend class GrPaint;
139ccb2e384a036f29d989d3c1468f879324e81a678egdaniel
140ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        GrColor fColor;
141ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        uint32_t fValidFlags;
142ccb2e384a036f29d989d3c1468f879324e81a678egdaniel        bool fIsSingleComponent;
143ab84fae29fdee95987b10c00ff34957476a66263egdaniel        bool fNonMulStageFound;
1441a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    };
1451a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel
146371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com    /**
1471a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel     * This function is used to perform optimizations. When called the invarientOuput param
148b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com     * indicate whether the input components to this effect in the FS will have known values.
1491a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel     * In inout the validFlags member is a bitfield of GrColorComponentFlags. The isSingleComponent
1501a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel     * member indicates whether the input will be 1 or 4 bytes. The function updates the members of
1511a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel     * inout to indicate known values of its output. A component of the color member only has
1521a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel     * meaning if the corresponding bit in validFlags is set.
153371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com     */
1541a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    void computeInvariantOutput(InvariantOutput* inout) const {
1551a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel        this->onComputeInvariantOutput(inout);
1561a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel#ifdef SK_DEBUG
1571a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel        inout->validate();
1581a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel#endif
1591a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    }
160168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com
161422e81aeb1f4078367c85efe591c7df8c33874ecbsalomon@google.com    /** This object, besides creating back-end-specific helper objects, is used for run-time-type-
162422e81aeb1f4078367c85efe591c7df8c33874ecbsalomon@google.com        identification. The factory should be an instance of templated class,
163b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        GrTBackendEffectFactory. It is templated on the subclass of GrProcessor. The subclass must
164b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        have a nested type (or typedef) named GLProcessor which will be the subclass of
165b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        GrGLProcessor created by the factory.
166ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com
167ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com        Example:
168b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        class MyCustomEffect : public GrProcessor {
169ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com        ...
170396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com            virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
171396e61fe440590744345e0c56970b26ab464591dbsalomon@google.com                return GrTBackendEffectFactory<MyCustomEffect>::getInstance();
172ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com            }
173ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com        ...
174ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com        };
175ae4f96a9e06df44f70c3d5f7324f5a7fabcd1026bsalomon@google.com     */
176b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendProcessorFactory& getFactory() const = 0;
177b88bbd2a5388ec2a5574d0ef7e43160c0ac37a3btomhudson@google.com
178a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    /** Human-meaningful string to identify this effect; may be embedded
179a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        in generated shader code. */
1802eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com    const char* name() const;
181289efe014ad7628de7cf2c5177a42cacd1e335adbsalomon@google.com
18250db75c871b203081a32190ab173f13c785a147fbsalomon@google.com    int numTextures() const { return fTextureAccesses.count(); }
183168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com
1846d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    /** Returns the access pattern for the texture at index. index must be valid according to
1856d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        numTextures(). */
18650db75c871b203081a32190ab173f13c785a147fbsalomon@google.com    const GrTextureAccess& textureAccess(int index) const { return *fTextureAccesses[index]; }
1876d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com
1886d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    /** Shortcut for textureAccess(index).texture(); */
1896d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); }
190a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
1918d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    /** Will this effect read the fragment position? */
1928d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    bool willReadFragmentPosition() const { return fWillReadFragmentPosition; }
193ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
194dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com    void* operator new(size_t size);
195dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com    void operator delete(void* target);
196dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com
197d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    void* operator new(size_t size, void* placement) {
198d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com        return ::operator new(size, placement);
199d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    }
200d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    void operator delete(void* target, void* placement) {
201d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com        ::operator delete(target, placement);
202d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    }
203d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com
20449586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    /**
205b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt      * Helper for down-casting to a GrProcessor subclass
20649586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt      */
20749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
20849586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt
20950db75c871b203081a32190ab173f13c785a147fbsalomon@google.comprotected:
21050db75c871b203081a32190ab173f13c785a147fbsalomon@google.com    /**
21191274b99722d9be62e077ab979c630c23cdd04b1skia.committer@gmail.com     * Subclasses call this from their constructor to register GrTextureAccesses. The effect
21291a798f121a2238639f8e2d08cc776d4f0236cebcommit-bot@chromium.org     * subclass manages the lifetime of the accesses (this function only stores a pointer). The
213b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * GrTextureAccess is typically a member field of the GrProcessor subclass. This must only be
214b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * called from the constructor because GrProcessors are immutable.
21550db75c871b203081a32190ab173f13c785a147fbsalomon@google.com     */
21650db75c871b203081a32190ab173f13c785a147fbsalomon@google.com    void addTextureAccess(const GrTextureAccess* textureAccess);
21750db75c871b203081a32190ab173f13c785a147fbsalomon@google.com
218b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrProcessor()
219b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        : fWillReadFragmentPosition(false) {}
2208d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org
2218d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    /**
2228d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org     * If the effect will generate a backend-specific effect that will read the fragment position
2238d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org     * in the FS then it must call this method from its constructor. Otherwise, the request to
2248d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org     * access the fragment position will be denied.
2258d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org     */
2268d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; }
22726e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
2280e08fc17e4718f7ce4e38f793695896473e96948bsalomon    SkDEBUGCODE(void assertTexturesEqual(const GrProcessor& other) const;)
22977af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com
2300e08fc17e4718f7ce4e38f793695896473e96948bsalomonprivate:
23168b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
2321a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    /**
2331a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel     * Subclass implements this to support getConstantColorComponents(...).
2341a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel     */
2351a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    virtual void onComputeInvariantOutput(InvariantOutput* inout) const = 0;
2360ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
237ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    SkSTArray<4, const GrTextureAccess*, true>   fTextureAccesses;
2388d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    bool                                         fWillReadFragmentPosition;
2390ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
24095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    typedef GrProgramElement INHERITED;
241168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com};
242168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com
243b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrFragmentProcessor : public GrProcessor {
244b0a8a377f832c59cee939ad721e1f87d378b7142joshualittpublic:
245b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrFragmentProcessor()
246b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        : INHERITED()
247b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        , fWillReadDstColor(false)
248b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        , fWillUseInputColor(true) {}
249b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
250b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendFragmentProcessorFactory& getFactory() const = 0;
251b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
252a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    int numTransforms() const { return fCoordTransforms.count(); }
253a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt
254a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    /** Returns the coordinate transformation at index. index must be valid according to
255a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt        numTransforms(). */
256a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
257a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt
258b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    /** Will this effect read the destination pixel value? */
259b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    bool willReadDstColor() const { return fWillReadDstColor; }
260b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
261b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    /** Will this effect read the source color value? */
262b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    bool willUseInputColor() const { return fWillUseInputColor; }
263b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
2640e08fc17e4718f7ce4e38f793695896473e96948bsalomon    /** Returns true if this and other effect conservatively draw identically. It can only return
2650e08fc17e4718f7ce4e38f793695896473e96948bsalomon        true when the two effects are of the same subclass (i.e. they return the same object from
2660e08fc17e4718f7ce4e38f793695896473e96948bsalomon        from getFactory()).
2670e08fc17e4718f7ce4e38f793695896473e96948bsalomon
2680e08fc17e4718f7ce4e38f793695896473e96948bsalomon        A return value of true from isEqual() should not be used to test whether the effects would
2690e08fc17e4718f7ce4e38f793695896473e96948bsalomon        generate the same shader code. To test for identical code generation use the effects' keys
2700e08fc17e4718f7ce4e38f793695896473e96948bsalomon        computed by the GrBackendEffectFactory. */
2710e08fc17e4718f7ce4e38f793695896473e96948bsalomon    bool isEqual(const GrFragmentProcessor& other) const {
2720e08fc17e4718f7ce4e38f793695896473e96948bsalomon        if (&this->getFactory() != &other.getFactory()) {
2730e08fc17e4718f7ce4e38f793695896473e96948bsalomon            return false;
2740e08fc17e4718f7ce4e38f793695896473e96948bsalomon        }
2750e08fc17e4718f7ce4e38f793695896473e96948bsalomon        bool result = this->onIsEqual(other);
2760e08fc17e4718f7ce4e38f793695896473e96948bsalomon#ifdef SK_DEBUG
2770e08fc17e4718f7ce4e38f793695896473e96948bsalomon        if (result) {
2780e08fc17e4718f7ce4e38f793695896473e96948bsalomon            this->assertTexturesEqual(other);
2790e08fc17e4718f7ce4e38f793695896473e96948bsalomon        }
2800e08fc17e4718f7ce4e38f793695896473e96948bsalomon#endif
2810e08fc17e4718f7ce4e38f793695896473e96948bsalomon        return result;
2820e08fc17e4718f7ce4e38f793695896473e96948bsalomon    }
2830e08fc17e4718f7ce4e38f793695896473e96948bsalomon
284b0a8a377f832c59cee939ad721e1f87d378b7142joshualittprotected:
285b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    /**
286a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * Fragment Processor subclasses call this from their constructor to register coordinate
287a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * transformations. The processor subclass manages the lifetime of the transformations (this
288a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * function only stores a pointer). The GrCoordTransform is typically a member field of the
289a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * GrProcessor subclass. When the matrix has perspective, the transformed coordinates will have
290a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * 3 components. Otherwise they'll have 2. This must only be called from the constructor because
291a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * GrProcessors are immutable.
292a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     */
293a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    void addCoordTransform(const GrCoordTransform*);
294a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt
295a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    /**
296b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * If the effect subclass will read the destination pixel value then it must call this function
297b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * from its constructor. Otherwise, when its generated backend-specific effect class attempts
298b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * to generate code that reads the destination pixel it will fail.
299b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     */
300b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    void setWillReadDstColor() { fWillReadDstColor = true; }
301b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
302b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    /**
303b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * If the effect will generate a result that does not depend on the input color value then it
304b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * must call this function from its constructor. Otherwise, when its generated backend-specific
305b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * code might fail during variable binding due to unused variables.
306b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     */
307b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    void setWillNotUseInputColor() { fWillUseInputColor = false; }
308b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
309b0a8a377f832c59cee939ad721e1f87d378b7142joshualittprivate:
3100e08fc17e4718f7ce4e38f793695896473e96948bsalomon    /** Subclass implements this to support isEqual(). It will only be called if it is known that
3110e08fc17e4718f7ce4e38f793695896473e96948bsalomon        the two effects are of the same subclass (i.e. they return the same object from
3120e08fc17e4718f7ce4e38f793695896473e96948bsalomon        getFactory()).*/
3130e08fc17e4718f7ce4e38f793695896473e96948bsalomon    virtual bool onIsEqual(const GrFragmentProcessor& other) const = 0;
3140e08fc17e4718f7ce4e38f793695896473e96948bsalomon
315a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    SkSTArray<4, const GrCoordTransform*, true>  fCoordTransforms;
316b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    bool                                         fWillReadDstColor;
317b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    bool                                         fWillUseInputColor;
318b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
319b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    typedef GrProcessor INHERITED;
320b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt};
321b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
322d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com/**
323d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com * This creates an effect outside of the effect memory pool. The effect's destructor will be called
324b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * at global destruction time. NAME will be the name of the created GrProcessor.
325d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com */
326b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#define GR_CREATE_STATIC_FRAGMENT_PROCESSOR(NAME, EFFECT_CLASS, ARGS)                             \
32797b9ab72cd5ee0cba4692082737266376425f27cbsalomonstatic SkAlignedSStorage<sizeof(EFFECT_CLASS)> g_##NAME##_Storage;                                \
328b0a8a377f832c59cee939ad721e1f87d378b7142joshualittstatic GrFragmentProcessor*                                                                       \
329b0a8a377f832c59cee939ad721e1f87d378b7142joshualittNAME SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), EFFECT_CLASS, ARGS);                          \
330b0a8a377f832c59cee939ad721e1f87d378b7142joshualittstatic SkAutoTDestroy<GrFragmentProcessor> NAME##_ad(NAME);
331d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com
332168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com#endif
333