GrXferProcessor.h revision 4dce32c46675efb901618161771d450241af4307
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 GrXferProcessor_DEFINED 9#define GrXferProcessor_DEFINED 10 11#include "GrColor.h" 12#include "GrProcessor.h" 13#include "GrTypes.h" 14#include "SkXfermode.h" 15 16class GrDrawTargetCaps; 17class GrGLCaps; 18class GrGLXferProcessor; 19class GrProcOptInfo; 20 21/** 22 * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst 23 * color. It does this by emitting fragment shader code and controlling the fixed-function blend 24 * state. The inputs to its shader code are the final computed src color and fractional pixel 25 * coverage. The GrXferProcessor's shader code writes the fragment shader output color that goes 26 * into the fixed-function blend. When dual-source blending is available, it may also write a 27 * seconday fragment shader output color. When allowed by the backend API, the GrXferProcessor may 28 * read the destination color. The GrXferProcessor is responsible for setting the blend coefficients 29 * and blend constant color. 30 * 31 * A GrXferProcessor is never installed directly into our draw state, but instead is created from a 32 * GrXPFactory once we have finalized the state of our draw. 33 */ 34class GrXferProcessor : public GrProcessor { 35public: 36 /** 37 * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer 38 * processor's GL backend implementation. 39 */ 40 virtual void getGLProcessorKey(const GrGLCaps& caps, 41 GrProcessorKeyBuilder* b) const = 0; 42 43 /** Returns a new instance of the appropriate *GL* implementation class 44 for the given GrXferProcessor; caller is responsible for deleting 45 the object. */ 46 virtual GrGLXferProcessor* createGLInstance() const = 0; 47 48 /** 49 * Optimizations for blending / coverage that an OptDrawState should apply to itself. 50 */ 51 enum OptFlags { 52 /** 53 * No optimizations needed 54 */ 55 kNone_Opt = 0, 56 /** 57 * The draw can be skipped completely. 58 */ 59 kSkipDraw_OptFlag = 0x1, 60 /** 61 * GrXferProcessor will ignore color, thus no need to provide 62 */ 63 kIgnoreColor_OptFlag = 0x2, 64 /** 65 * GrXferProcessor will ignore coverage, thus no need to provide 66 */ 67 kIgnoreCoverage_OptFlag = 0x4, 68 /** 69 * Clear color stages and override input color to that returned by getOptimizations 70 */ 71 kOverrideColor_OptFlag = 0x8, 72 /** 73 * Set CoverageDrawing_StateBit 74 */ 75 kSetCoverageDrawing_OptFlag = 0x10, 76 }; 77 78 GR_DECL_BITFIELD_OPS_FRIENDS(OptFlags); 79 80 /** 81 * Determines which optimizations (as described by the ptFlags above) can be performed by 82 * the draw with this xfer processor. If this function is called, the xfer processor may change 83 * its state to reflected the given blend optimizations. If the XP needs to see a specific input 84 * color to blend correctly, it will set the OverrideColor flag and the output parameter 85 * overrideColor will be the required value that should be passed into the XP. 86 * A caller who calls this function on a XP is required to honor the returned OptFlags 87 * and color values for its draw. 88 */ 89 virtual OptFlags getOptimizations(const GrProcOptInfo& colorPOI, 90 const GrProcOptInfo& coveragePOI, 91 bool doesStencilWrite, 92 GrColor* overrideColor, 93 const GrDrawTargetCaps& caps) = 0; 94 95 struct BlendInfo { 96 BlendInfo() : fWriteColor(true) {} 97 98 GrBlendCoeff fSrcBlend; 99 GrBlendCoeff fDstBlend; 100 GrColor fBlendConstant; 101 bool fWriteColor; 102 }; 103 104 virtual void getBlendInfo(BlendInfo* blendInfo) const = 0; 105 106 /** Will this prceossor read the destination pixel value? */ 107 bool willReadDstColor() const { return fWillReadDstColor; } 108 109 /** 110 * Returns whether or not this xferProcossor will set a secondary output to be used with dual 111 * source blending. 112 */ 113 virtual bool hasSecondaryOutput() const { return false; } 114 115 /** Returns true if this and other processor conservatively draw identically. It can only return 116 true when the two processor are of the same subclass (i.e. they return the same object from 117 from getFactory()). 118 119 A return value of true from isEqual() should not be used to test whether the processor would 120 generate the same shader code. To test for identical code generation use getGLProcessorKey*/ 121 122 bool isEqual(const GrXferProcessor& that) const { 123 if (this->classID() != that.classID()) { 124 return false; 125 } 126 return this->onIsEqual(that); 127 } 128 129protected: 130 GrXferProcessor() : fWillReadDstColor(false) {} 131 132 /** 133 * If the prceossor subclass will read the destination pixel value then it must call this 134 * function from its constructor. Otherwise, when its generated backend-specific prceossor class 135 * attempts to generate code that reads the destination pixel it will fail. 136 */ 137 void setWillReadDstColor() { fWillReadDstColor = true; } 138 139private: 140 virtual bool onIsEqual(const GrXferProcessor&) const = 0; 141 142 bool fWillReadDstColor; 143 144 typedef GrFragmentProcessor INHERITED; 145}; 146 147GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags); 148 149/** 150 * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is 151 * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the 152 * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the 153 * draw information to create a GrXferProcessor (XP) which can implement the desired blending for 154 * the draw. 155 * 156 * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it 157 * creates will have. For example, can it create an XP that supports RGB coverage or will the XP 158 * blend with the destination color. 159 */ 160class GrXPFactory : public SkRefCnt { 161public: 162 virtual GrXferProcessor* createXferProcessor(const GrProcOptInfo& colorPOI, 163 const GrProcOptInfo& coveragePOI) const = 0; 164 165 /** 166 * This function returns true if the GrXferProcessor generated from this factory will be able to 167 * correctly blend when using RGB coverage. The knownColor and knownColorFlags represent the 168 * final computed color from the color stages. 169 */ 170 virtual bool supportsRGBCoverage(GrColor knownColor, uint32_t knownColorFlags) const = 0; 171 172 /** 173 * Depending on color blend mode requested it may or may not be possible to correctly blend with 174 * fractional pixel coverage generated by the fragment shader. 175 * 176 * This function considers the known color and coverage input into the xfer processor and 177 * certain state information (colorWriteDisabled) to determine whether 178 * coverage can be handled correctly. 179 */ 180 virtual bool canApplyCoverage(const GrProcOptInfo& colorPOI, 181 const GrProcOptInfo& coveragePOI) const = 0; 182 183 184 struct InvariantOutput { 185 bool fWillBlendWithDst; 186 GrColor fBlendedColor; 187 uint32_t fBlendedColorFlags; 188 }; 189 190 /** 191 * This function returns known information about the output of the xfer processor produced by 192 * this xp factory. The invariant color information returned by this function refers to the 193 * final color produced after all blending. 194 */ 195 virtual void getInvariantOutput(const GrProcOptInfo& colorPOI, const GrProcOptInfo& coveragePOI, 196 InvariantOutput*) const = 0; 197 198 /** 199 * Determines whether multiplying the computed per-pixel color by the pixel's fractional 200 * coverage before the blend will give the correct final destination color. In general it 201 * will not as coverage is applied after blending. 202 */ 203 virtual bool canTweakAlphaForCoverage() const = 0; 204 205 /** 206 * Returns true if the XP generated by this factory will read dst. 207 */ 208 virtual bool willReadDst() const = 0; 209 210 bool isEqual(const GrXPFactory& that) const { 211 if (this->classID() != that.classID()) { 212 return false; 213 } 214 return this->onIsEqual(that); 215 } 216 217 /** 218 * Helper for down-casting to a GrXPFactory subclass 219 */ 220 template <typename T> const T& cast() const { return *static_cast<const T*>(this); } 221 222 uint32_t classID() const { SkASSERT(kIllegalXPFClassID != fClassID); return fClassID; } 223 224protected: 225 GrXPFactory() : fClassID(kIllegalXPFClassID) {} 226 227 template <typename XPF_SUBCLASS> void initClassID() { 228 static uint32_t kClassID = GenClassID(); 229 fClassID = kClassID; 230 } 231 232 uint32_t fClassID; 233 234private: 235 virtual bool onIsEqual(const GrXPFactory&) const = 0; 236 237 static uint32_t GenClassID() { 238 // fCurrXPFactoryID has been initialized to kIllegalXPFactoryID. The 239 // atomic inc returns the old value not the incremented value. So we add 240 // 1 to the returned value. 241 uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&gCurrXPFClassID)) + 1; 242 if (!id) { 243 SkFAIL("This should never wrap as it should only be called once for each GrXPFactory " 244 "subclass."); 245 } 246 return id; 247 } 248 249 enum { 250 kIllegalXPFClassID = 0, 251 }; 252 static int32_t gCurrXPFClassID; 253 254 typedef GrProgramElement INHERITED; 255}; 256 257#endif 258 259