1 /* 2 * Copyright 2014 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 8 #ifndef GrFragmentProcessor_DEFINED 9 #define GrFragmentProcessor_DEFINED 10 11 #include "GrProcessor.h" 12 13 class GrCoordTransform; 14 class GrGLSLFragmentProcessor; 15 class GrInvariantOutput; 16 class GrPipeline; 17 class GrProcessorKeyBuilder; 18 class GrShaderCaps; 19 class GrSwizzle; 20 21 /** Provides custom fragment shader code. Fragment processors receive an input color (vec4f) and 22 produce an output color. They may reference textures and uniforms. They may use 23 GrCoordTransforms to receive a transformation of the local coordinates that map from local space 24 to the fragment being processed. 25 */ 26 class GrFragmentProcessor : public GrResourceIOProcessor, public GrProgramElement { 27 public: 28 /** 29 * In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to 30 * only consider the input color's alpha. However, there is a competing desire to have reusable 31 * GrFragmentProcessor subclasses that can be used in other scenarios where the entire input 32 * color is considered. This function exists to filter the input color and pass it to a FP. It 33 * does so by returning a parent FP that multiplies the passed in FPs output by the parent's 34 * input alpha. The passed in FP will not receive an input color. 35 */ 36 static sk_sp<GrFragmentProcessor> MulOutputByInputAlpha(sk_sp<GrFragmentProcessor>); 37 38 /** 39 * This assumes that the input color to the returned processor will be unpremul and that the 40 * passed processor (which becomes the returned processor's child) produces a premul output. 41 * The result of the returned processor is a premul of its input color modulated by the child 42 * processor's premul output. 43 */ 44 static sk_sp<GrFragmentProcessor> MakeInputPremulAndMulByOutput(sk_sp<GrFragmentProcessor>); 45 46 /** 47 * Returns a parent fragment processor that adopts the passed fragment processor as a child. 48 * The parent will ignore its input color and instead feed the passed in color as input to the 49 * child. 50 */ 51 static sk_sp<GrFragmentProcessor> OverrideInput(sk_sp<GrFragmentProcessor>, GrColor4f); 52 53 /** 54 * Returns a fragment processor that premuls the input before calling the passed in fragment 55 * processor. 56 */ 57 static sk_sp<GrFragmentProcessor> PremulInput(sk_sp<GrFragmentProcessor>); 58 59 /** 60 * Returns a fragment processor that calls the passed in fragment processor, and then premuls 61 * the output. 62 */ 63 static sk_sp<GrFragmentProcessor> PremulOutput(sk_sp<GrFragmentProcessor>); 64 65 /** 66 * Returns a fragment processor that calls the passed in fragment processor, and then unpremuls 67 * the output. 68 */ 69 static sk_sp<GrFragmentProcessor> UnpremulOutput(sk_sp<GrFragmentProcessor>); 70 71 /** 72 * Returns a fragment processor that calls the passed in fragment processor, and then swizzles 73 * the output. 74 */ 75 static sk_sp<GrFragmentProcessor> SwizzleOutput(sk_sp<GrFragmentProcessor>, const GrSwizzle&); 76 77 /** 78 * Returns a fragment processor that runs the passed in array of fragment processors in a 79 * series. The original input is passed to the first, the first's output is passed to the 80 * second, etc. The output of the returned processor is the output of the last processor of the 81 * series. 82 * 83 * The array elements with be moved. 84 */ 85 static sk_sp<GrFragmentProcessor> RunInSeries(sk_sp<GrFragmentProcessor>*, int cnt); 86 87 ~GrFragmentProcessor() override; 88 89 GrGLSLFragmentProcessor* createGLSLInstance() const; 90 getGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b)91 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const { 92 this->onGetGLSLProcessorKey(caps, b); 93 for (int i = 0; i < fChildProcessors.count(); ++i) { 94 fChildProcessors[i]->getGLSLProcessorKey(caps, b); 95 } 96 } 97 numCoordTransforms()98 int numCoordTransforms() const { return fCoordTransforms.count(); } 99 100 /** Returns the coordinate transformation at index. index must be valid according to 101 numTransforms(). */ coordTransform(int index)102 const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; } 103 coordTransforms()104 const SkTArray<const GrCoordTransform*, true>& coordTransforms() const { 105 return fCoordTransforms; 106 } 107 numChildProcessors()108 int numChildProcessors() const { return fChildProcessors.count(); } 109 childProcessor(int index)110 const GrFragmentProcessor& childProcessor(int index) const { return *fChildProcessors[index]; } 111 112 bool instantiate(GrResourceProvider*) const; 113 114 /** Do any of the coordtransforms for this processor require local coords? */ usesLocalCoords()115 bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); } 116 117 /** 118 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color 119 * output under the following scenario: 120 * * all the color fragment processors report true to this query, 121 * * all the coverage fragment processors report true to this query, 122 * * the blend mode arithmetic allows for it it. 123 * To be compatible a fragment processor's output must be a modulation of its input color or 124 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color 125 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed 126 * value cannot depend on the input's color channels unless it unpremultiplies the input color 127 * channels by the input alpha. 128 */ compatibleWithCoverageAsAlpha()129 bool compatibleWithCoverageAsAlpha() const { 130 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag); 131 } 132 133 /** 134 * If this is true then all opaque input colors to the processor produce opaque output colors. 135 */ preservesOpaqueInput()136 bool preservesOpaqueInput() const { 137 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag); 138 } 139 140 /** 141 * Tests whether given a constant input color the processor produces a constant output color 142 * (for all fragments). If true outputColor will contain the constant color produces for 143 * inputColor. 144 */ hasConstantOutputForConstantInput(GrColor4f inputColor,GrColor4f * outputColor)145 bool hasConstantOutputForConstantInput(GrColor4f inputColor, GrColor4f* outputColor) const { 146 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) { 147 *outputColor = this->constantOutputForConstantInput(inputColor); 148 return true; 149 } 150 return false; 151 } hasConstantOutputForConstantInput()152 bool hasConstantOutputForConstantInput() const { 153 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag); 154 } 155 156 /** Returns true if this and other processor conservatively draw identically. It can only return 157 true when the two processor are of the same subclass (i.e. they return the same object from 158 from getFactory()). 159 160 A return value of true from isEqual() should not be used to test whether the processor would 161 generate the same shader code. To test for identical code generation use getGLSLProcessorKey 162 */ 163 bool isEqual(const GrFragmentProcessor& that) const; 164 165 /** 166 * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter 167 * case the tree rooted at each FP in the GrPipeline is visited successively. 168 */ 169 class Iter : public SkNoncopyable { 170 public: Iter(const GrFragmentProcessor * fp)171 explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); } 172 explicit Iter(const GrPipeline& pipeline); 173 const GrFragmentProcessor* next(); 174 175 private: 176 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack; 177 }; 178 179 /** 180 * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts 181 * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same 182 * order as Iter and each of an FP's Ts are visited in order. 183 */ 184 template <typename T, typename BASE, 185 int (BASE::*COUNT)() const, 186 const T& (BASE::*GET)(int) const> 187 class FPItemIter : public SkNoncopyable { 188 public: FPItemIter(const GrFragmentProcessor * fp)189 explicit FPItemIter(const GrFragmentProcessor* fp) 190 : fCurrFP(nullptr) 191 , fCTIdx(0) 192 , fFPIter(fp) { 193 fCurrFP = fFPIter.next(); 194 } FPItemIter(const GrPipeline & pipeline)195 explicit FPItemIter(const GrPipeline& pipeline) 196 : fCurrFP(nullptr) 197 , fCTIdx(0) 198 , fFPIter(pipeline) { 199 fCurrFP = fFPIter.next(); 200 } 201 next()202 const T* next() { 203 if (!fCurrFP) { 204 return nullptr; 205 } 206 while (fCTIdx == (fCurrFP->*COUNT)()) { 207 fCTIdx = 0; 208 fCurrFP = fFPIter.next(); 209 if (!fCurrFP) { 210 return nullptr; 211 } 212 } 213 return &(fCurrFP->*GET)(fCTIdx++); 214 } 215 216 private: 217 const GrFragmentProcessor* fCurrFP; 218 int fCTIdx; 219 GrFragmentProcessor::Iter fFPIter; 220 }; 221 222 using CoordTransformIter = FPItemIter<GrCoordTransform, 223 GrFragmentProcessor, 224 &GrFragmentProcessor::numCoordTransforms, 225 &GrFragmentProcessor::coordTransform>; 226 227 using TextureAccessIter = FPItemIter<TextureSampler, 228 GrResourceIOProcessor, 229 &GrResourceIOProcessor::numTextureSamplers, 230 &GrResourceIOProcessor::textureSampler>; 231 232 protected: 233 enum OptimizationFlags : uint32_t { 234 kNone_OptimizationFlags, 235 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1, 236 kPreservesOpaqueInput_OptimizationFlag = 0x2, 237 kConstantOutputForConstantInput_OptimizationFlag = 0x4, 238 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag | 239 kPreservesOpaqueInput_OptimizationFlag | 240 kConstantOutputForConstantInput_OptimizationFlag 241 }; 242 GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags) 243 GrFragmentProcessor(OptimizationFlags optimizationFlags)244 GrFragmentProcessor(OptimizationFlags optimizationFlags) : fFlags(optimizationFlags) { 245 SkASSERT((fFlags & ~kAll_OptimizationFlags) == 0); 246 } 247 optimizationFlags()248 OptimizationFlags optimizationFlags() const { 249 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags); 250 } 251 252 /** 253 * This allows one subclass to access another subclass's implementation of 254 * constantOutputForConstantInput. It must only be called when 255 * hasConstantOutputForConstantInput() is known to be true. 256 */ ConstantOutputForConstantInput(const GrFragmentProcessor & fp,GrColor4f input)257 static GrColor4f ConstantOutputForConstantInput(const GrFragmentProcessor& fp, 258 GrColor4f input) { 259 SkASSERT(fp.hasConstantOutputForConstantInput()); 260 return fp.constantOutputForConstantInput(input); 261 } 262 263 /** 264 * Fragment Processor subclasses call this from their constructor to register coordinate 265 * transformations. Coord transforms provide a mechanism for a processor to receive coordinates 266 * in their FS code. The matrix expresses a transformation from local space. For a given 267 * fragment the matrix will be applied to the local coordinate that maps to the fragment. 268 * 269 * When the transformation has perspective, the transformed coordinates will have 270 * 3 components. Otherwise they'll have 2. 271 * 272 * This must only be called from the constructor because GrProcessors are immutable. The 273 * processor subclass manages the lifetime of the transformations (this function only stores a 274 * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass. 275 * 276 * A processor subclass that has multiple methods of construction should always add its coord 277 * transforms in a consistent order. The non-virtual implementation of isEqual() automatically 278 * compares transforms and will assume they line up across the two processor instances. 279 */ 280 void addCoordTransform(const GrCoordTransform*); 281 282 /** 283 * FragmentProcessor subclasses call this from their constructor to register any child 284 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord 285 * transforms have been added. 286 * This is for processors whose shader code will be composed of nested processors whose output 287 * colors will be combined somehow to produce its output color. Registering these child 288 * processors will allow the ProgramBuilder to automatically handle their transformed coords and 289 * texture accesses and mangle their uniform and output color names. 290 */ 291 int registerChildProcessor(sk_sp<GrFragmentProcessor> child); 292 293 private: addPendingIOs()294 void addPendingIOs() const override { GrResourceIOProcessor::addPendingIOs(); } removeRefs()295 void removeRefs() const override { GrResourceIOProcessor::removeRefs(); } pendingIOComplete()296 void pendingIOComplete() const override { GrResourceIOProcessor::pendingIOComplete(); } 297 298 void notifyRefCntIsZero() const final; 299 constantOutputForConstantInput(GrColor4f)300 virtual GrColor4f constantOutputForConstantInput(GrColor4f /* inputColor */) const { 301 SkFAIL("Subclass must override this if advertising this optimization."); 302 return GrColor4f::TransparentBlack(); 303 } 304 305 /** Returns a new instance of the appropriate *GL* implementation class 306 for the given GrFragmentProcessor; caller is responsible for deleting 307 the object. */ 308 virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0; 309 310 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */ 311 virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0; 312 313 /** 314 * Subclass implements this to support isEqual(). It will only be called if it is known that 315 * the two processors are of the same subclass (i.e. they return the same object from 316 * getFactory()). The processor subclass should not compare its coord transforms as that will 317 * be performed automatically in the non-virtual isEqual(). 318 */ 319 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0; 320 321 bool hasSameTransforms(const GrFragmentProcessor&) const; 322 323 enum PrivateFlags { 324 kFirstPrivateFlag = kAll_OptimizationFlags + 1, 325 kUsesLocalCoords_Flag = kFirstPrivateFlag, 326 }; 327 328 mutable uint32_t fFlags = 0; 329 330 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms; 331 332 /** 333 * This is not SkSTArray<1, sk_sp<GrFragmentProcessor>> because this class holds strong 334 * references until notifyRefCntIsZero and then it holds pending executions. 335 */ 336 SkSTArray<1, GrFragmentProcessor*, true> fChildProcessors; 337 338 typedef GrResourceIOProcessor INHERITED; 339 }; 340 341 GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags) 342 343 #endif 344