blob: e9259979f0af3946deddf5523ed93d2fd194ecce [file] [log] [blame]
tomhudson@google.com168e6342012-04-18 17:49:20 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
bsalomon@google.com8ea78d82012-10-24 20:11:30 +00008#ifndef GrEffect_DEFINED
9#define GrEffect_DEFINED
tomhudson@google.com168e6342012-04-18 17:49:20 +000010
bsalomon@google.com371e1052013-01-11 21:08:55 +000011#include "GrColor.h"
bsalomon@google.com6f261be2012-10-24 19:07:10 +000012#include "GrEffectUnitTest.h"
bsalomon95740982014-09-04 13:12:37 -070013#include "GrProgramElement.h"
joshualitt249af152014-09-15 11:41:13 -070014#include "GrShaderVar.h"
bsalomon@google.com047696c2012-09-11 13:29:29 +000015#include "GrTextureAccess.h"
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +000016#include "GrTypesPriv.h"
joshualitt249af152014-09-15 11:41:13 -070017#include "SkString.h"
tomhudson@google.com07eecdc2012-04-20 18:35:38 +000018
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +000019class GrBackendEffectFactory;
tomhudson@google.com168e6342012-04-18 17:49:20 +000020class GrContext;
bsalomon@google.com77af6802013-10-02 13:04:56 +000021class GrCoordTransform;
bsalomon95740982014-09-04 13:12:37 -070022
bsalomon@google.com50db75c2013-01-11 13:54:30 +000023/** Provides custom vertex shader, fragment shader, uniform data for a particular stage of the
24 Ganesh shading pipeline.
bsalomon@google.com289efe02012-05-21 20:57:59 +000025 Subclasses must have a function that produces a human-readable name:
26 static const char* Name();
bsalomon@google.com50db75c2013-01-11 13:54:30 +000027 GrEffect objects *must* be immutable: after being constructed, their fields may not change.
bsalomon@google.com0ac6af42013-01-16 15:16:18 +000028
bsalomon97b9ab72014-07-08 06:52:35 -070029 Dynamically allocated GrEffects are managed by a per-thread memory pool. The ref count of an
30 effect must reach 0 before the thread terminates and the pool is destroyed. To create a static
31 effect use the macro GR_CREATE_STATIC_EFFECT declared below.
bsalomon@google.com289efe02012-05-21 20:57:59 +000032 */
bsalomon95740982014-09-04 13:12:37 -070033class GrEffect : public GrProgramElement {
tomhudson@google.com168e6342012-04-18 17:49:20 +000034public:
bsalomon@google.coma469c282012-10-24 18:28:34 +000035 SK_DECLARE_INST_COUNT(GrEffect)
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000036
bsalomon@google.coma469c282012-10-24 18:28:34 +000037 virtual ~GrEffect();
tomhudson@google.com168e6342012-04-18 17:49:20 +000038
bsalomon@google.com371e1052013-01-11 21:08:55 +000039 /**
bsalomon@google.com371e1052013-01-11 21:08:55 +000040 * This function is used to perform optimizations. When called the color and validFlags params
bsalomon@google.comb8eb2e82013-03-28 13:46:42 +000041 * indicate whether the input components to this effect in the FS will have known values.
42 * validFlags is a bitfield of GrColorComponentFlags. The function updates both params to
43 * indicate known values of its output. A component of the color param only has meaning if the
44 * corresponding bit in validFlags is set.
bsalomon@google.com371e1052013-01-11 21:08:55 +000045 */
46 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const = 0;
tomhudson@google.com168e6342012-04-18 17:49:20 +000047
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +000048 /** Will this effect read the source color value? */
49 bool willUseInputColor() const { return fWillUseInputColor; }
50
bsalomon@google.com422e81a2012-10-25 14:11:03 +000051 /** This object, besides creating back-end-specific helper objects, is used for run-time-type-
52 identification. The factory should be an instance of templated class,
bsalomon@google.com396e61f2012-10-25 19:00:29 +000053 GrTBackendEffectFactory. It is templated on the subclass of GrEffect. The subclass must have
bsalomon@google.com422e81a2012-10-25 14:11:03 +000054 a nested type (or typedef) named GLEffect which will be the subclass of GrGLEffect created
55 by the factory.
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000056
57 Example:
bsalomon@google.com8ea78d82012-10-24 20:11:30 +000058 class MyCustomEffect : public GrEffect {
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000059 ...
bsalomon@google.com396e61f2012-10-25 19:00:29 +000060 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
61 return GrTBackendEffectFactory<MyCustomEffect>::getInstance();
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000062 }
63 ...
64 };
65 */
bsalomon@google.com396e61f2012-10-25 19:00:29 +000066 virtual const GrBackendEffectFactory& getFactory() const = 0;
tomhudson@google.comb88bbd22012-05-01 12:48:07 +000067
bsalomon@google.com68b58c92013-01-17 16:50:08 +000068 /** Returns true if this and other effect conservatively draw identically. It can only return
69 true when the two effects are of the same subclass (i.e. they return the same object from
70 from getFactory()).
tomhudson@google.com1dcfa1f2012-07-09 18:21:28 +000071
bsalomon@google.com68b58c92013-01-17 16:50:08 +000072 A return value of true from isEqual() should not be used to test whether the effects would
bsalomon63e99f72014-07-21 08:03:14 -070073 generate the same shader code. To test for identical code generation use the effects' keys
74 computed by the GrBackendEffectFactory.
tomhudson@google.comd0c1a062012-07-12 17:23:52 +000075 */
bsalomon97b9ab72014-07-08 06:52:35 -070076 bool isEqual(const GrEffect& other) const {
77 if (&this->getFactory() != &other.getFactory()) {
78 return false;
79 }
80 bool result = this->onIsEqual(other);
81#ifdef SK_DEBUG
82 if (result) {
83 this->assertEquality(other);
84 }
85#endif
86 return result;
bsalomon@google.com68b58c92013-01-17 16:50:08 +000087 }
tomhudson@google.com168e6342012-04-18 17:49:20 +000088
twiz@google.coma5e65ec2012-08-02 15:15:16 +000089 /** Human-meaningful string to identify this effect; may be embedded
90 in generated shader code. */
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +000091 const char* name() const;
bsalomon@google.com289efe02012-05-21 20:57:59 +000092
bsalomon@google.com77af6802013-10-02 13:04:56 +000093 int numTransforms() const { return fCoordTransforms.count(); }
94
95 /** Returns the coordinate transformation at index. index must be valid according to
96 numTransforms(). */
97 const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
98
bsalomon@google.com50db75c2013-01-11 13:54:30 +000099 int numTextures() const { return fTextureAccesses.count(); }
tomhudson@google.comd8f856c2012-05-10 12:13:36 +0000100
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000101 /** Returns the access pattern for the texture at index. index must be valid according to
102 numTextures(). */
bsalomon@google.com50db75c2013-01-11 13:54:30 +0000103 const GrTextureAccess& textureAccess(int index) const { return *fTextureAccesses[index]; }
bsalomon@google.com6d003d12012-09-11 15:45:20 +0000104
105 /** Shortcut for textureAccess(index).texture(); */
106 GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); }
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000107
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000108 /** Will this effect read the destination pixel value? */
commit-bot@chromium.org8d47ddc2013-05-09 14:55:46 +0000109 bool willReadDstColor() const { return fWillReadDstColor; }
110
111 /** Will this effect read the fragment position? */
112 bool willReadFragmentPosition() const { return fWillReadFragmentPosition; }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000113
commit-bot@chromium.org234d4fb2013-09-30 19:55:49 +0000114 /** Will this effect emit custom vertex shader code?
joshualitt30ba4362014-08-21 20:18:45 -0700115 (To set this value the effect must inherit from GrEffect.) */
kkinnunenec56e452014-08-25 22:21:16 -0700116 bool requiresVertexShader() const { return fRequiresVertexShader; }
commit-bot@chromium.org234d4fb2013-09-30 19:55:49 +0000117
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000118 static const int kMaxVertexAttribs = 2;
joshualitt249af152014-09-15 11:41:13 -0700119 typedef SkSTArray<kMaxVertexAttribs, GrShaderVar, true> VertexAttribArray;
120
121 const VertexAttribArray& getVertexAttribs() const { return fVertexAttribs; }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000122
tomhudson@google.comdcba4c22012-07-24 21:36:16 +0000123 void* operator new(size_t size);
124 void operator delete(void* target);
125
bsalomon@google.comd42aca32013-04-23 15:37:27 +0000126 void* operator new(size_t size, void* placement) {
127 return ::operator new(size, placement);
128 }
129 void operator delete(void* target, void* placement) {
130 ::operator delete(target, placement);
131 }
132
joshualitt49586be2014-09-16 08:21:41 -0700133 /**
134 * Helper for down-casting to a GrEffect subclass
135 */
136 template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
137
bsalomon@google.com50db75c2013-01-11 13:54:30 +0000138protected:
139 /**
bsalomon@google.com77af6802013-10-02 13:04:56 +0000140 * Subclasses call this from their constructor to register coordinate transformations. The
141 * effect subclass manages the lifetime of the transformations (this function only stores a
142 * pointer). The GrCoordTransform is typically a member field of the GrEffect subclass. When the
143 * matrix has perspective, the transformed coordinates will have 3 components. Otherwise they'll
144 * have 2. This must only be called from the constructor because GrEffects are immutable.
145 */
146 void addCoordTransform(const GrCoordTransform* coordTransform);
147
148 /**
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000149 * Subclasses call this from their constructor to register GrTextureAccesses. The effect
commit-bot@chromium.org91a798f2013-09-06 15:31:06 +0000150 * subclass manages the lifetime of the accesses (this function only stores a pointer). The
bsalomon@google.com77af6802013-10-02 13:04:56 +0000151 * GrTextureAccess is typically a member field of the GrEffect subclass. This must only be
commit-bot@chromium.org91a798f2013-09-06 15:31:06 +0000152 * called from the constructor because GrEffects are immutable.
bsalomon@google.com50db75c2013-01-11 13:54:30 +0000153 */
154 void addTextureAccess(const GrTextureAccess* textureAccess);
155
commit-bot@chromium.org234d4fb2013-09-30 19:55:49 +0000156 GrEffect()
157 : fWillReadDstColor(false)
158 , fWillReadFragmentPosition(false)
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000159 , fWillUseInputColor(true)
kkinnunenec56e452014-08-25 22:21:16 -0700160 , fRequiresVertexShader(false) {}
bsalomon@google.com0ac6af42013-01-16 15:16:18 +0000161
bsalomon0139ae32014-07-08 10:30:37 -0700162 /**
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000163 * If the effect subclass will read the destination pixel value then it must call this function
164 * from its constructor. Otherwise, when its generated backend-specific effect class attempts
165 * to generate code that reads the destination pixel it will fail.
166 */
commit-bot@chromium.org8d47ddc2013-05-09 14:55:46 +0000167 void setWillReadDstColor() { fWillReadDstColor = true; }
168
169 /**
170 * If the effect will generate a backend-specific effect that will read the fragment position
171 * in the FS then it must call this method from its constructor. Otherwise, the request to
172 * access the fragment position will be denied.
173 */
174 void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; }
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000175
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000176 /**
177 * If the effect will generate a result that does not depend on the input color value then it must
178 * call this function from its constructor. Otherwise, when its generated backend-specific code
179 * might fail during variable binding due to unused variables.
180 */
181 void setWillNotUseInputColor() { fWillUseInputColor = false; }
182
tomhudson@google.comd0c1a062012-07-12 17:23:52 +0000183private:
bsalomon@google.com77af6802013-10-02 13:04:56 +0000184 SkDEBUGCODE(void assertEquality(const GrEffect& other) const;)
185
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000186 /** Subclass implements this to support isEqual(). It will only be called if it is known that
bsalomon@google.com6340a412013-01-22 19:55:59 +0000187 the two effects are of the same subclass (i.e. they return the same object from
188 getFactory()).*/
bsalomon@google.com8a252f72013-01-22 20:35:13 +0000189 virtual bool onIsEqual(const GrEffect& other) const = 0;
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000190
joshualitt249af152014-09-15 11:41:13 -0700191 friend class GrGeometryProcessor; // to set fRequiresVertexShader and build fVertexAttribTypes.
bsalomon@google.com0ac6af42013-01-16 15:16:18 +0000192
bsalomon@google.com77af6802013-10-02 13:04:56 +0000193 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000194 SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses;
joshualitt249af152014-09-15 11:41:13 -0700195 VertexAttribArray fVertexAttribs;
commit-bot@chromium.org8d47ddc2013-05-09 14:55:46 +0000196 bool fWillReadDstColor;
197 bool fWillReadFragmentPosition;
commit-bot@chromium.orga34995e2013-10-23 05:42:03 +0000198 bool fWillUseInputColor;
kkinnunenec56e452014-08-25 22:21:16 -0700199 bool fRequiresVertexShader;
bsalomon@google.com0ac6af42013-01-16 15:16:18 +0000200
bsalomon95740982014-09-04 13:12:37 -0700201 typedef GrProgramElement INHERITED;
tomhudson@google.com168e6342012-04-18 17:49:20 +0000202};
203
bsalomon@google.comd42aca32013-04-23 15:37:27 +0000204/**
205 * This creates an effect outside of the effect memory pool. The effect's destructor will be called
bsalomon97b9ab72014-07-08 06:52:35 -0700206 * at global destruction time. NAME will be the name of the created GrEffect.
bsalomon@google.comd42aca32013-04-23 15:37:27 +0000207 */
208#define GR_CREATE_STATIC_EFFECT(NAME, EFFECT_CLASS, ARGS) \
bsalomon97b9ab72014-07-08 06:52:35 -0700209static SkAlignedSStorage<sizeof(EFFECT_CLASS)> g_##NAME##_Storage; \
210static GrEffect* NAME SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), EFFECT_CLASS, ARGS); \
211static SkAutoTDestroy<GrEffect> NAME##_ad(NAME);
bsalomon@google.comd42aca32013-04-23 15:37:27 +0000212
tomhudson@google.com168e6342012-04-18 17:49:20 +0000213#endif