1 /* 2 * Copyright 2015 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 #include "GrXferProcessor.h" 9 #include "GrPipeline.h" 10 #include "gl/GrGLCaps.h" 11 12 GrXferProcessor::GrXferProcessor() 13 : fWillReadDstColor(false) 14 , fDstReadUsesMixedSamples(false) 15 , fDstTextureOffset() { 16 } 17 18 GrXferProcessor::GrXferProcessor(const DstTexture* dstTexture, 19 bool willReadDstColor, 20 bool hasMixedSamples) 21 : fWillReadDstColor(willReadDstColor) 22 , fDstReadUsesMixedSamples(willReadDstColor && hasMixedSamples) 23 , fDstTextureOffset() { 24 if (dstTexture && dstTexture->texture()) { 25 SkASSERT(willReadDstColor); 26 fDstTexture.reset(dstTexture->texture()); 27 fDstTextureOffset = dstTexture->offset(); 28 this->addTextureSampler(&fDstTexture); 29 } 30 } 31 32 GrXferProcessor::OptFlags GrXferProcessor::getOptimizations( 33 const FragmentProcessorAnalysis& analysis) const { 34 return this->onGetOptimizations(analysis); 35 } 36 37 bool GrXferProcessor::hasSecondaryOutput() const { 38 if (!this->willReadDstColor()) { 39 return this->onHasSecondaryOutput(); 40 } 41 return this->dstReadUsesMixedSamples(); 42 } 43 44 void GrXferProcessor::getBlendInfo(BlendInfo* blendInfo) const { 45 blendInfo->reset(); 46 if (!this->willReadDstColor()) { 47 this->onGetBlendInfo(blendInfo); 48 } else if (this->dstReadUsesMixedSamples()) { 49 blendInfo->fDstBlend = kIS2A_GrBlendCoeff; 50 } 51 } 52 53 void GrXferProcessor::getGLSLProcessorKey(const GrShaderCaps& caps, 54 GrProcessorKeyBuilder* b) const { 55 uint32_t key = this->willReadDstColor() ? 0x1 : 0x0; 56 if (key) { 57 if (const GrTexture* dstTexture = this->getDstTexture()) { 58 key |= 0x2; 59 if (kTopLeft_GrSurfaceOrigin == dstTexture->origin()) { 60 key |= 0x4; 61 } 62 } 63 if (this->dstReadUsesMixedSamples()) { 64 key |= 0x8; 65 } 66 } 67 b->add32(key); 68 this->onGetGLSLProcessorKey(caps, b); 69 } 70 71 GrXferBarrierType GrXferProcessor::xferBarrierType(const GrRenderTarget* rt, 72 const GrCaps& caps) const { 73 SkASSERT(rt); 74 if (static_cast<const GrSurface*>(rt) == this->getDstTexture()) { 75 // Texture barriers are required when a shader reads and renders to the same texture. 76 SkASSERT(caps.textureBarrierSupport()); 77 return kTexture_GrXferBarrierType; 78 } 79 return this->onXferBarrier(rt, caps); 80 } 81 82 #ifdef SK_DEBUG 83 static const char* equation_string(GrBlendEquation eq) { 84 switch (eq) { 85 case kAdd_GrBlendEquation: 86 return "add"; 87 case kSubtract_GrBlendEquation: 88 return "subtract"; 89 case kReverseSubtract_GrBlendEquation: 90 return "reverse_subtract"; 91 case kScreen_GrBlendEquation: 92 return "screen"; 93 case kOverlay_GrBlendEquation: 94 return "overlay"; 95 case kDarken_GrBlendEquation: 96 return "darken"; 97 case kLighten_GrBlendEquation: 98 return "lighten"; 99 case kColorDodge_GrBlendEquation: 100 return "color_dodge"; 101 case kColorBurn_GrBlendEquation: 102 return "color_burn"; 103 case kHardLight_GrBlendEquation: 104 return "hard_light"; 105 case kSoftLight_GrBlendEquation: 106 return "soft_light"; 107 case kDifference_GrBlendEquation: 108 return "difference"; 109 case kExclusion_GrBlendEquation: 110 return "exclusion"; 111 case kMultiply_GrBlendEquation: 112 return "multiply"; 113 case kHSLHue_GrBlendEquation: 114 return "hsl_hue"; 115 case kHSLSaturation_GrBlendEquation: 116 return "hsl_saturation"; 117 case kHSLColor_GrBlendEquation: 118 return "hsl_color"; 119 case kHSLLuminosity_GrBlendEquation: 120 return "hsl_luminosity"; 121 }; 122 return ""; 123 } 124 125 static const char* coeff_string(GrBlendCoeff coeff) { 126 switch (coeff) { 127 case kZero_GrBlendCoeff: 128 return "zero"; 129 case kOne_GrBlendCoeff: 130 return "one"; 131 case kSC_GrBlendCoeff: 132 return "src_color"; 133 case kISC_GrBlendCoeff: 134 return "inv_src_color"; 135 case kDC_GrBlendCoeff: 136 return "dst_color"; 137 case kIDC_GrBlendCoeff: 138 return "inv_dst_color"; 139 case kSA_GrBlendCoeff: 140 return "src_alpha"; 141 case kISA_GrBlendCoeff: 142 return "inv_src_alpha"; 143 case kDA_GrBlendCoeff: 144 return "dst_alpha"; 145 case kIDA_GrBlendCoeff: 146 return "inv_dst_alpha"; 147 case kConstC_GrBlendCoeff: 148 return "const_color"; 149 case kIConstC_GrBlendCoeff: 150 return "inv_const_color"; 151 case kConstA_GrBlendCoeff: 152 return "const_alpha"; 153 case kIConstA_GrBlendCoeff: 154 return "inv_const_alpha"; 155 case kS2C_GrBlendCoeff: 156 return "src2_color"; 157 case kIS2C_GrBlendCoeff: 158 return "inv_src2_color"; 159 case kS2A_GrBlendCoeff: 160 return "src2_alpha"; 161 case kIS2A_GrBlendCoeff: 162 return "inv_src2_alpha"; 163 } 164 return ""; 165 } 166 167 SkString GrXferProcessor::BlendInfo::dump() const { 168 SkString out; 169 out.printf("write_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)", 170 fWriteColor, equation_string(fEquation), coeff_string(fSrcBlend), 171 coeff_string(fDstBlend), fBlendConstant); 172 return out; 173 } 174 #endif 175 176 /////////////////////////////////////////////////////////////////////////////// 177 178 bool GrXPFactory::WillNeedDstTexture(const GrXPFactory* factory, const GrCaps& caps, 179 const GrProcessorSet::FragmentProcessorAnalysis& analysis) { 180 bool result; 181 if (factory) { 182 result = !caps.shaderCaps()->dstReadInShaderSupport() && 183 factory->willReadDstInShader(caps, analysis); 184 } else { 185 result = GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(caps, analysis); 186 } 187 return result; 188 } 189 190 bool GrXPFactory::CompatibleWithCoverageAsAlpha(const GrXPFactory* factory, bool colorIsOpaque) { 191 if (factory) { 192 return factory->compatibleWithCoverageAsAlpha(colorIsOpaque); 193 } 194 return GrPorterDuffXPFactory::SrcOverIsCompatibleWithCoverageAsAlpha(); 195 } 196 197 bool GrXPFactory::CanCombineOverlappedStencilAndCover(const GrXPFactory* factory, 198 bool colorIsOpaque) { 199 if (factory) { 200 return factory->canCombineOverlappedStencilAndCover(colorIsOpaque); 201 } 202 return GrPorterDuffXPFactory::SrcOverCanCombineOverlappedStencilAndCover(colorIsOpaque); 203 } 204 205 GrXferProcessor* GrXPFactory::createXferProcessor(const FragmentProcessorAnalysis& analysis, 206 bool hasMixedSamples, 207 const DstTexture* dstTexture, 208 const GrCaps& caps) const { 209 #ifdef SK_DEBUG 210 if (this->willReadDstInShader(caps, analysis)) { 211 if (!caps.shaderCaps()->dstReadInShaderSupport()) { 212 SkASSERT(dstTexture && dstTexture->texture()); 213 } else { 214 SkASSERT(!dstTexture || !dstTexture->texture()); 215 } 216 } else { 217 SkASSERT(!dstTexture || !dstTexture->texture()); 218 } 219 SkASSERT(!hasMixedSamples || caps.shaderCaps()->dualSourceBlendingSupport()); 220 #endif 221 return this->onCreateXferProcessor(caps, analysis, hasMixedSamples, dstTexture); 222 } 223