GrProcessor.h revision ab84fae29fdee95987b10c00ff34957476a66263
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
17868b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    /** Returns true if this and other effect conservatively draw identically. It can only return
17968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        true when the two effects are of the same subclass (i.e. they return the same object from
18068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        from getFactory()).
18168b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
18268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        A return value of true from isEqual() should not be used to test whether the effects would
18363e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon        generate the same shader code. To test for identical code generation use the effects' keys
18463e99f7a03b2ac90ae7a00232674fd39c0bdcc68bsalomon        computed by the GrBackendEffectFactory.
185d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.com     */
186b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    bool isEqual(const GrProcessor& other) const {
18797b9ab72cd5ee0cba4692082737266376425f27cbsalomon        if (&this->getFactory() != &other.getFactory()) {
18897b9ab72cd5ee0cba4692082737266376425f27cbsalomon            return false;
18997b9ab72cd5ee0cba4692082737266376425f27cbsalomon        }
19097b9ab72cd5ee0cba4692082737266376425f27cbsalomon        bool result = this->onIsEqual(other);
19197b9ab72cd5ee0cba4692082737266376425f27cbsalomon#ifdef SK_DEBUG
19297b9ab72cd5ee0cba4692082737266376425f27cbsalomon        if (result) {
19397b9ab72cd5ee0cba4692082737266376425f27cbsalomon            this->assertEquality(other);
19497b9ab72cd5ee0cba4692082737266376425f27cbsalomon        }
19597b9ab72cd5ee0cba4692082737266376425f27cbsalomon#endif
19697b9ab72cd5ee0cba4692082737266376425f27cbsalomon        return result;
19768b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    }
198d8f856c32b679d9f5a9926feac005e2c0186f83ftomhudson@google.com
199a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com    /** Human-meaningful string to identify this effect; may be embedded
200a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        in generated shader code. */
2012eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com    const char* name() const;
202289efe014ad7628de7cf2c5177a42cacd1e335adbsalomon@google.com
20350db75c871b203081a32190ab173f13c785a147fbsalomon@google.com    int numTextures() const { return fTextureAccesses.count(); }
204168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com
2056d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    /** Returns the access pattern for the texture at index. index must be valid according to
2066d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        numTextures(). */
20750db75c871b203081a32190ab173f13c785a147fbsalomon@google.com    const GrTextureAccess& textureAccess(int index) const { return *fTextureAccesses[index]; }
2086d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com
2096d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    /** Shortcut for textureAccess(index).texture(); */
2106d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); }
211a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
2128d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    /** Will this effect read the fragment position? */
2138d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    bool willReadFragmentPosition() const { return fWillReadFragmentPosition; }
214ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
215dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com    void* operator new(size_t size);
216dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com    void operator delete(void* target);
217dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com
218d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    void* operator new(size_t size, void* placement) {
219d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com        return ::operator new(size, placement);
220d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    }
221d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    void operator delete(void* target, void* placement) {
222d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com        ::operator delete(target, placement);
223d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com    }
224d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com
22549586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    /**
226b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt      * Helper for down-casting to a GrProcessor subclass
22749586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt      */
22849586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt    template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
22949586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt
23050db75c871b203081a32190ab173f13c785a147fbsalomon@google.comprotected:
23150db75c871b203081a32190ab173f13c785a147fbsalomon@google.com    /**
23291274b99722d9be62e077ab979c630c23cdd04b1skia.committer@gmail.com     * Subclasses call this from their constructor to register GrTextureAccesses. The effect
23391a798f121a2238639f8e2d08cc776d4f0236cebcommit-bot@chromium.org     * subclass manages the lifetime of the accesses (this function only stores a pointer). The
234b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * GrTextureAccess is typically a member field of the GrProcessor subclass. This must only be
235b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * called from the constructor because GrProcessors are immutable.
23650db75c871b203081a32190ab173f13c785a147fbsalomon@google.com     */
23750db75c871b203081a32190ab173f13c785a147fbsalomon@google.com    void addTextureAccess(const GrTextureAccess* textureAccess);
23850db75c871b203081a32190ab173f13c785a147fbsalomon@google.com
239b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrProcessor()
240b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        : fWillReadFragmentPosition(false) {}
2418d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org
2428d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    /**
2438d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org     * If the effect will generate a backend-specific effect that will read the fragment position
2448d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org     * in the FS then it must call this method from its constructor. Otherwise, the request to
2458d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org     * access the fragment position will be denied.
2468d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org     */
2478d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; }
24826e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
249d0c1a06cb98dd4a009dfa79e37ba6ca23a8c180btomhudson@google.comprivate:
250b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    SkDEBUGCODE(void assertEquality(const GrProcessor& other) const;)
25177af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com
25268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com    /** Subclass implements this to support isEqual(). It will only be called if it is known that
2536340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com        the two effects are of the same subclass (i.e. they return the same object from
2546340a41108633ac1ce5941e5cd30538630c4c55bbsalomon@google.com        getFactory()).*/
255b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual bool onIsEqual(const GrProcessor& other) const = 0;
25668b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com
2571a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    /**
2581a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel     * Subclass implements this to support getConstantColorComponents(...).
2591a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel     */
2601a8ecdfb73a15de600d5779b75d7c4b61863c50begdaniel    virtual void onComputeInvariantOutput(InvariantOutput* inout) const = 0;
2610ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
262ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    SkSTArray<4, const GrTextureAccess*, true>   fTextureAccesses;
2638d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org    bool                                         fWillReadFragmentPosition;
2640ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com
26595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    typedef GrProgramElement INHERITED;
266168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com};
267168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com
268b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrFragmentProcessor : public GrProcessor {
269b0a8a377f832c59cee939ad721e1f87d378b7142joshualittpublic:
270b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    GrFragmentProcessor()
271b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        : INHERITED()
272b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        , fWillReadDstColor(false)
273b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt        , fWillUseInputColor(true) {}
274b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
275b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    virtual const GrBackendFragmentProcessorFactory& getFactory() const = 0;
276b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
277a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    int numTransforms() const { return fCoordTransforms.count(); }
278a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt
279a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    /** Returns the coordinate transformation at index. index must be valid according to
280a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt        numTransforms(). */
281a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
282a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt
283b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    /** Will this effect read the destination pixel value? */
284b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    bool willReadDstColor() const { return fWillReadDstColor; }
285b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
286b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    /** Will this effect read the source color value? */
287b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    bool willUseInputColor() const { return fWillUseInputColor; }
288b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
289b0a8a377f832c59cee939ad721e1f87d378b7142joshualittprotected:
290b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    /**
291a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * Fragment Processor subclasses call this from their constructor to register coordinate
292a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * transformations. The processor subclass manages the lifetime of the transformations (this
293a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * function only stores a pointer). The GrCoordTransform is typically a member field of the
294a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * GrProcessor subclass. When the matrix has perspective, the transformed coordinates will have
295a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * 3 components. Otherwise they'll have 2. This must only be called from the constructor because
296a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     * GrProcessors are immutable.
297a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt     */
298a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    void addCoordTransform(const GrCoordTransform*);
299a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt
300a5305a110ab5201d5dadd40cbe711582d5ac4996joshualitt    /**
301b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * If the effect subclass will read the destination pixel value then it must call this function
302b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * from its constructor. Otherwise, when its generated backend-specific effect class attempts
303b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * to generate code that reads the destination pixel it will fail.
304b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     */
305b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    void setWillReadDstColor() { fWillReadDstColor = true; }
306b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
307b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    /**
308b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * If the effect will generate a result that does not depend on the input color value then it
309b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * must call this function from its constructor. Otherwise, when its generated backend-specific
310b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     * code might fail during variable binding due to unused variables.
311b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt     */
312b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt    void setWillNotUseInputColor() { fWillUseInputColor = false; }
313b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt
314b0a8a377f832c59cee939ad721e1f87d378b7142joshualittprivate:
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