16251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon/*
26251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon * Copyright 2014 Google Inc.
36251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon *
46251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon * Use of this source code is governed by a BSD-style license that can be
56251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon * found in the LICENSE file.
66251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon */
76251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
86251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon#ifndef GrFragmentProcessor_DEFINED
96251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon#define GrFragmentProcessor_DEFINED
106251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
116251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon#include "GrProcessor.h"
126251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
136251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomonclass GrCoordTransform;
14e9c0fc616d2a1632c285885b9b656b68ca8d4f24jvanverthclass GrGLSLCaps;
15eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittclass GrGLFragmentProcessor;
16eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittclass GrProcessorKeyBuilder;
176251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
186251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon/** Provides custom fragment shader code. Fragment processors receive an input color (vec4f) and
196251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    produce an output color. They may reference textures and uniforms. They may use
206251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    GrCoordTransforms to receive a transformation of the local coordinates that map from local space
216251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    to the fragment being processed.
226251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon */
236251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomonclass GrFragmentProcessor : public GrProcessor {
246251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomonpublic:
256251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    GrFragmentProcessor()
266251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon        : INHERITED()
27290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt        , fWillUseInputColor(true)
28290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt        , fUsesLocalCoords(false) {}
296251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
30eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */
31cfc18867d982119d9dc2888bf09f1093012daaddjvanverth    virtual void getGLProcessorKey(const GrGLSLCaps& caps,
32eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt                                   GrProcessorKeyBuilder* b) const = 0;
33eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
34eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    /** Returns a new instance of the appropriate *GL* implementation class
35eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        for the given GrFragmentProcessor; caller is responsible for deleting
36eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        the object. */
37eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    virtual GrGLFragmentProcessor* createGLInstance() const = 0;
38eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt
39eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    /** Human-meaningful string to identify this GrFragmentProcessor; may be embedded
40eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        in generated shader code. */
41eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    virtual const char* name() const = 0;
426251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
436251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    int numTransforms() const { return fCoordTransforms.count(); }
446251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
456251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    /** Returns the coordinate transformation at index. index must be valid according to
466251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon        numTransforms(). */
476251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
486251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
49abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt    const SkTArray<const GrCoordTransform*, true>& coordTransforms() const {
50abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt        return fCoordTransforms;
51abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt    }
52abb52a1a70a81915c6196e0fb3e9bcb05e8be14djoshualitt
536251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    /** Will this prceossor read the source color value? */
546251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    bool willUseInputColor() const { return fWillUseInputColor; }
556251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
56290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    /** Do any of the coordtransforms for this processor require local coords? */
57290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    bool usesLocalCoords() const { return fUsesLocalCoords; }
58290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt
59eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt    /** Returns true if this and other processor conservatively draw identically. It can only return
60eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        true when the two processor are of the same subclass (i.e. they return the same object from
616251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon        from getFactory()).
626251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
63eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        A return value of true from isEqual() should not be used to test whether the processor would
64eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        generate the same shader code. To test for identical code generation use getGLProcessorKey*/
65420d7e9a79358908850c74192b4949375563449absalomon    bool isEqual(const GrFragmentProcessor& that) const {
66eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt        if (this->classID() != that.classID() ||
67420d7e9a79358908850c74192b4949375563449absalomon            !this->hasSameTransforms(that) ||
68420d7e9a79358908850c74192b4949375563449absalomon            !this->hasSameTextureAccesses(that)) {
696251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon            return false;
706251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon        }
71420d7e9a79358908850c74192b4949375563449absalomon        return this->onIsEqual(that);
726251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    }
736251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
7456995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    /**
7556995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * This function is used to perform optimizations. When called the invarientOuput param
7656995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * indicate whether the input components to this processor in the FS will have known values.
7756995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * In inout the validFlags member is a bitfield of GrColorComponentFlags. The isSingleComponent
7856995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * member indicates whether the input will be 1 or 4 bytes. The function updates the members of
7956995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * inout to indicate known values of its output. A component of the color member only has
8056995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * meaning if the corresponding bit in validFlags is set.
8156995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     */
8256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    void computeInvariantOutput(GrInvariantOutput* inout) const;
8356995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt
846251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomonprotected:
856251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    /**
866251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon     * Fragment Processor subclasses call this from their constructor to register coordinate
87de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * transformations. Coord transforms provide a mechanism for a processor to receive coordinates
88de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * in their FS code. The matrix expresses a transformation from local space. For a given
89de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * fragment the matrix will be applied to the local coordinate that maps to the fragment.
90de258cd6b402c4da78b66e88191ad02162d87916bsalomon     *
91de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * When the transformation has perspective, the transformed coordinates will have
92de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * 3 components. Otherwise they'll have 2.
93de258cd6b402c4da78b66e88191ad02162d87916bsalomon     *
94de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * This must only be called from the constructor because GrProcessors are immutable. The
95de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * processor subclass manages the lifetime of the transformations (this function only stores a
96de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass.
97de258cd6b402c4da78b66e88191ad02162d87916bsalomon     *
98de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * A processor subclass that has multiple methods of construction should always add its coord
99de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * transforms in a consistent order. The non-virtual implementation of isEqual() automatically
100de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * compares transforms and will assume they line up across the two processor instances.
1016251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon     */
1026251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    void addCoordTransform(const GrCoordTransform*);
1036251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
1046251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    /**
1056251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon     * If the prceossor will generate a result that does not depend on the input color value then it
1066251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon     * must call this function from its constructor. Otherwise, when its generated backend-specific
1076251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon     * code might fail during variable binding due to unused variables.
1086251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon     */
1096251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    void setWillNotUseInputColor() { fWillUseInputColor = false; }
1106251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
11156995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    /**
11256995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     * Subclass implements this to support getConstantColorComponents(...).
11356995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt     */
11456995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt    virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const = 0;
11556995b5cc00c9c83bd5fcf86bca9a67e939a96cbjoshualitt
1166251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomonprivate:
117de258cd6b402c4da78b66e88191ad02162d87916bsalomon    /**
118de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * Subclass implements this to support isEqual(). It will only be called if it is known that
119de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * the two processors are of the same subclass (i.e. they return the same object from
120de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * getFactory()). The processor subclass should not compare its coord transforms as that will
121de258cd6b402c4da78b66e88191ad02162d87916bsalomon     * be performed automatically in the non-virtual isEqual().
122de258cd6b402c4da78b66e88191ad02162d87916bsalomon     */
123de258cd6b402c4da78b66e88191ad02162d87916bsalomon    virtual bool onIsEqual(const GrFragmentProcessor&) const = 0;
124de258cd6b402c4da78b66e88191ad02162d87916bsalomon
125de258cd6b402c4da78b66e88191ad02162d87916bsalomon    bool hasSameTransforms(const GrFragmentProcessor&) const;
1266251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
1276251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    SkSTArray<4, const GrCoordTransform*, true>  fCoordTransforms;
1286251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    bool                                         fWillUseInputColor;
129290c09b8bbd8d221d363150e2ce87158f4668df0joshualitt    bool                                         fUsesLocalCoords;
1306251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
1316251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon    typedef GrProcessor INHERITED;
1326251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon};
1336251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon
1346251d17dfadbbeba8a7e72affde5cbdbd0c0c95fbsalomon#endif
135