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 GrProcessor { 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 /** Do any of the coordtransforms for this processor require local coords? */ usesLocalCoords()113 bool usesLocalCoords() const { return SkToBool(fFlags & kUsesLocalCoords_Flag); } 114 115 /** Does this FP need a vector to the nearest edge? */ usesDistanceVectorField()116 bool usesDistanceVectorField() const { 117 return SkToBool(fFlags & kUsesDistanceVectorField_Flag); 118 } 119 120 /** 121 * A GrDrawOp may premultiply its antialiasing coverage into its GrGeometryProcessor's color 122 * output under the following scenario: 123 * * all the color fragment processors report true to this query, 124 * * all the coverage fragment processors report true to this query, 125 * * the blend mode arithmetic allows for it it. 126 * To be compatible a fragment processor's output must be a modulation of its input color or 127 * alpha with a computed premultiplied color or alpha that is in 0..1 range. The computed color 128 * or alpha that is modulated against the input cannot depend on the input's alpha. The computed 129 * value cannot depend on the input's color channels unless it unpremultiplies the input color 130 * channels by the input alpha. 131 */ compatibleWithCoverageAsAlpha()132 bool compatibleWithCoverageAsAlpha() const { 133 return SkToBool(fFlags & kCompatibleWithCoverageAsAlpha_OptimizationFlag); 134 } 135 136 /** 137 * If this is true then all opaque input colors to the processor produce opaque output colors. 138 */ preservesOpaqueInput()139 bool preservesOpaqueInput() const { 140 return SkToBool(fFlags & kPreservesOpaqueInput_OptimizationFlag); 141 } 142 143 /** 144 * Tests whether given a constant input color the processor produces a constant output color 145 * (for all fragments). If true outputColor will contain the constant color produces for 146 * inputColor. 147 */ hasConstantOutputForConstantInput(GrColor4f inputColor,GrColor4f * outputColor)148 bool hasConstantOutputForConstantInput(GrColor4f inputColor, GrColor4f* outputColor) const { 149 if (fFlags & kConstantOutputForConstantInput_OptimizationFlag) { 150 *outputColor = this->constantOutputForConstantInput(inputColor); 151 return true; 152 } 153 return false; 154 } hasConstantOutputForConstantInput()155 bool hasConstantOutputForConstantInput() const { 156 return SkToBool(fFlags & kConstantOutputForConstantInput_OptimizationFlag); 157 } 158 159 /** Returns true if this and other processor conservatively draw identically. It can only return 160 true when the two processor are of the same subclass (i.e. they return the same object from 161 from getFactory()). 162 163 A return value of true from isEqual() should not be used to test whether the processor would 164 generate the same shader code. To test for identical code generation use getGLSLProcessorKey 165 */ 166 bool isEqual(const GrFragmentProcessor& that) const; 167 168 /** 169 * Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter 170 * case the tree rooted at each FP in the GrPipeline is visited successively. 171 */ 172 class Iter : public SkNoncopyable { 173 public: Iter(const GrFragmentProcessor * fp)174 explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); } 175 explicit Iter(const GrPipeline& pipeline); 176 const GrFragmentProcessor* next(); 177 178 private: 179 SkSTArray<4, const GrFragmentProcessor*, true> fFPStack; 180 }; 181 182 /** 183 * Iterates over all the Ts owned by a GrFragmentProcessor and its children or over all the Ts 184 * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same 185 * order as Iter and each of an FP's Ts are visited in order. 186 */ 187 template <typename T, typename BASE, 188 int (BASE::*COUNT)() const, 189 const T& (BASE::*GET)(int) const> 190 class FPItemIter : public SkNoncopyable { 191 public: FPItemIter(const GrFragmentProcessor * fp)192 explicit FPItemIter(const GrFragmentProcessor* fp) 193 : fCurrFP(nullptr) 194 , fCTIdx(0) 195 , fFPIter(fp) { 196 fCurrFP = fFPIter.next(); 197 } FPItemIter(const GrPipeline & pipeline)198 explicit FPItemIter(const GrPipeline& pipeline) 199 : fCurrFP(nullptr) 200 , fCTIdx(0) 201 , fFPIter(pipeline) { 202 fCurrFP = fFPIter.next(); 203 } 204 next()205 const T* next() { 206 if (!fCurrFP) { 207 return nullptr; 208 } 209 while (fCTIdx == (fCurrFP->*COUNT)()) { 210 fCTIdx = 0; 211 fCurrFP = fFPIter.next(); 212 if (!fCurrFP) { 213 return nullptr; 214 } 215 } 216 return &(fCurrFP->*GET)(fCTIdx++); 217 } 218 219 private: 220 const GrFragmentProcessor* fCurrFP; 221 int fCTIdx; 222 GrFragmentProcessor::Iter fFPIter; 223 }; 224 225 using CoordTransformIter = FPItemIter<GrCoordTransform, 226 GrFragmentProcessor, 227 &GrFragmentProcessor::numCoordTransforms, 228 &GrFragmentProcessor::coordTransform>; 229 230 using TextureAccessIter = FPItemIter<TextureSampler, 231 GrProcessor, 232 &GrProcessor::numTextureSamplers, 233 &GrProcessor::textureSampler>; 234 235 protected: 236 enum OptimizationFlags : uint32_t { 237 kNone_OptimizationFlags, 238 kCompatibleWithCoverageAsAlpha_OptimizationFlag = 0x1, 239 kPreservesOpaqueInput_OptimizationFlag = 0x2, 240 kConstantOutputForConstantInput_OptimizationFlag = 0x4, 241 kAll_OptimizationFlags = kCompatibleWithCoverageAsAlpha_OptimizationFlag | 242 kPreservesOpaqueInput_OptimizationFlag | 243 kConstantOutputForConstantInput_OptimizationFlag 244 }; 245 GR_DECL_BITFIELD_OPS_FRIENDS(OptimizationFlags) 246 GrFragmentProcessor(OptimizationFlags optimizationFlags)247 GrFragmentProcessor(OptimizationFlags optimizationFlags) : fFlags(optimizationFlags) { 248 SkASSERT((fFlags & ~kAll_OptimizationFlags) == 0); 249 } 250 optimizationFlags()251 OptimizationFlags optimizationFlags() const { 252 return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags); 253 } 254 255 /** 256 * This allows one subclass to access another subclass's implementation of 257 * constantOutputForConstantInput. It must only be called when 258 * hasConstantOutputForConstantInput() is known to be true. 259 */ ConstantOutputForConstantInput(const GrFragmentProcessor & fp,GrColor4f input)260 static GrColor4f ConstantOutputForConstantInput(const GrFragmentProcessor& fp, 261 GrColor4f input) { 262 SkASSERT(fp.hasConstantOutputForConstantInput()); 263 return fp.constantOutputForConstantInput(input); 264 } 265 266 /** 267 * Fragment Processor subclasses call this from their constructor to register coordinate 268 * transformations. Coord transforms provide a mechanism for a processor to receive coordinates 269 * in their FS code. The matrix expresses a transformation from local space. For a given 270 * fragment the matrix will be applied to the local coordinate that maps to the fragment. 271 * 272 * When the transformation has perspective, the transformed coordinates will have 273 * 3 components. Otherwise they'll have 2. 274 * 275 * This must only be called from the constructor because GrProcessors are immutable. The 276 * processor subclass manages the lifetime of the transformations (this function only stores a 277 * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass. 278 * 279 * A processor subclass that has multiple methods of construction should always add its coord 280 * transforms in a consistent order. The non-virtual implementation of isEqual() automatically 281 * compares transforms and will assume they line up across the two processor instances. 282 */ 283 void addCoordTransform(const GrCoordTransform*); 284 285 /** 286 * FragmentProcessor subclasses call this from their constructor to register any child 287 * FragmentProcessors they have. This must be called AFTER all texture accesses and coord 288 * transforms have been added. 289 * This is for processors whose shader code will be composed of nested processors whose output 290 * colors will be combined somehow to produce its output color. Registering these child 291 * processors will allow the ProgramBuilder to automatically handle their transformed coords and 292 * texture accesses and mangle their uniform and output color names. 293 */ 294 int registerChildProcessor(sk_sp<GrFragmentProcessor> child); 295 296 /** 297 * Sub-classes should call this in their constructors if they need access to a distance 298 * vector field to the nearest edge 299 */ setWillUseDistanceVectorField()300 void setWillUseDistanceVectorField() { fFlags |= kUsesDistanceVectorField_Flag; } 301 302 private: 303 void notifyRefCntIsZero() const final; 304 constantOutputForConstantInput(GrColor4f)305 virtual GrColor4f constantOutputForConstantInput(GrColor4f /* inputColor */) const { 306 SkFAIL("Subclass must override this if advertising this optimization."); 307 return GrColor4f::TransparentBlack(); 308 } 309 310 /** Returns a new instance of the appropriate *GL* implementation class 311 for the given GrFragmentProcessor; caller is responsible for deleting 312 the object. */ 313 virtual GrGLSLFragmentProcessor* onCreateGLSLInstance() const = 0; 314 315 /** Implemented using GLFragmentProcessor::GenKey as described in this class's comment. */ 316 virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0; 317 318 /** 319 * Subclass implements this to support isEqual(). It will only be called if it is known that 320 * the two processors are of the same subclass (i.e. they return the same object from 321 * getFactory()). The processor subclass should not compare its coord transforms as that will 322 * be performed automatically in the non-virtual isEqual(). 323 */ 324 virtual bool onIsEqual(const GrFragmentProcessor&) const = 0; 325 326 bool hasSameTransforms(const GrFragmentProcessor&) const; 327 328 enum PrivateFlags { 329 kFirstPrivateFlag = kAll_OptimizationFlags + 1, 330 kUsesLocalCoords_Flag = kFirstPrivateFlag, 331 kUsesDistanceVectorField_Flag = kFirstPrivateFlag << 1, 332 }; 333 334 mutable uint32_t fFlags = 0; 335 336 SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms; 337 338 /** 339 * This is not SkSTArray<1, sk_sp<GrFragmentProcessor>> because this class holds strong 340 * references until notifyRefCntIsZero and then it holds pending executions. 341 */ 342 SkSTArray<1, GrFragmentProcessor*, true> fChildProcessors; 343 344 typedef GrProcessor INHERITED; 345 }; 346 347 GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags) 348 349 #endif 350