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