1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/gpu/GrXferProcessor.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h" 11cb93a386Sopenharmony_ci#include "src/gpu/GrPipeline.h" 12cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 13cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLProgramDataManager.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ciGrXferProcessor::GrXferProcessor(ClassID classID) 16cb93a386Sopenharmony_ci : INHERITED(classID) 17cb93a386Sopenharmony_ci , fWillReadDstColor(false) 18cb93a386Sopenharmony_ci , fIsLCD(false) {} 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ciGrXferProcessor::GrXferProcessor(ClassID classID, bool willReadDstColor, 21cb93a386Sopenharmony_ci GrProcessorAnalysisCoverage coverage) 22cb93a386Sopenharmony_ci : INHERITED(classID) 23cb93a386Sopenharmony_ci , fWillReadDstColor(willReadDstColor) 24cb93a386Sopenharmony_ci , fIsLCD(GrProcessorAnalysisCoverage::kLCD == coverage) {} 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_cibool GrXferProcessor::hasSecondaryOutput() const { 27cb93a386Sopenharmony_ci if (!this->willReadDstColor()) { 28cb93a386Sopenharmony_ci return this->onHasSecondaryOutput(); 29cb93a386Sopenharmony_ci } 30cb93a386Sopenharmony_ci return false; 31cb93a386Sopenharmony_ci} 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_civoid GrXferProcessor::addToKey(const GrShaderCaps& caps, 34cb93a386Sopenharmony_ci GrProcessorKeyBuilder* b, 35cb93a386Sopenharmony_ci const GrSurfaceOrigin* originIfDstTexture, 36cb93a386Sopenharmony_ci bool usesInputAttachmentForDstRead) const { 37cb93a386Sopenharmony_ci uint32_t key = this->willReadDstColor() ? 0x1 : 0x0; 38cb93a386Sopenharmony_ci if (key) { 39cb93a386Sopenharmony_ci if (originIfDstTexture) { 40cb93a386Sopenharmony_ci key |= 0x2; 41cb93a386Sopenharmony_ci if (kTopLeft_GrSurfaceOrigin == *originIfDstTexture) { 42cb93a386Sopenharmony_ci key |= 0x4; 43cb93a386Sopenharmony_ci } 44cb93a386Sopenharmony_ci if (usesInputAttachmentForDstRead) { 45cb93a386Sopenharmony_ci key |= 0x8; 46cb93a386Sopenharmony_ci } 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci } 49cb93a386Sopenharmony_ci if (fIsLCD) { 50cb93a386Sopenharmony_ci key |= 0x10; 51cb93a386Sopenharmony_ci } 52cb93a386Sopenharmony_ci b->add32(key); 53cb93a386Sopenharmony_ci this->onAddToKey(caps, b); 54cb93a386Sopenharmony_ci} 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci#ifdef SK_DEBUG 57cb93a386Sopenharmony_cistatic const char* equation_string(GrBlendEquation eq) { 58cb93a386Sopenharmony_ci switch (eq) { 59cb93a386Sopenharmony_ci case kAdd_GrBlendEquation: 60cb93a386Sopenharmony_ci return "add"; 61cb93a386Sopenharmony_ci case kSubtract_GrBlendEquation: 62cb93a386Sopenharmony_ci return "subtract"; 63cb93a386Sopenharmony_ci case kReverseSubtract_GrBlendEquation: 64cb93a386Sopenharmony_ci return "reverse_subtract"; 65cb93a386Sopenharmony_ci case kScreen_GrBlendEquation: 66cb93a386Sopenharmony_ci return "screen"; 67cb93a386Sopenharmony_ci case kOverlay_GrBlendEquation: 68cb93a386Sopenharmony_ci return "overlay"; 69cb93a386Sopenharmony_ci case kDarken_GrBlendEquation: 70cb93a386Sopenharmony_ci return "darken"; 71cb93a386Sopenharmony_ci case kLighten_GrBlendEquation: 72cb93a386Sopenharmony_ci return "lighten"; 73cb93a386Sopenharmony_ci case kColorDodge_GrBlendEquation: 74cb93a386Sopenharmony_ci return "color_dodge"; 75cb93a386Sopenharmony_ci case kColorBurn_GrBlendEquation: 76cb93a386Sopenharmony_ci return "color_burn"; 77cb93a386Sopenharmony_ci case kHardLight_GrBlendEquation: 78cb93a386Sopenharmony_ci return "hard_light"; 79cb93a386Sopenharmony_ci case kSoftLight_GrBlendEquation: 80cb93a386Sopenharmony_ci return "soft_light"; 81cb93a386Sopenharmony_ci case kDifference_GrBlendEquation: 82cb93a386Sopenharmony_ci return "difference"; 83cb93a386Sopenharmony_ci case kExclusion_GrBlendEquation: 84cb93a386Sopenharmony_ci return "exclusion"; 85cb93a386Sopenharmony_ci case kMultiply_GrBlendEquation: 86cb93a386Sopenharmony_ci return "multiply"; 87cb93a386Sopenharmony_ci case kHSLHue_GrBlendEquation: 88cb93a386Sopenharmony_ci return "hsl_hue"; 89cb93a386Sopenharmony_ci case kHSLSaturation_GrBlendEquation: 90cb93a386Sopenharmony_ci return "hsl_saturation"; 91cb93a386Sopenharmony_ci case kHSLColor_GrBlendEquation: 92cb93a386Sopenharmony_ci return "hsl_color"; 93cb93a386Sopenharmony_ci case kHSLLuminosity_GrBlendEquation: 94cb93a386Sopenharmony_ci return "hsl_luminosity"; 95cb93a386Sopenharmony_ci case kIllegal_GrBlendEquation: 96cb93a386Sopenharmony_ci SkASSERT(false); 97cb93a386Sopenharmony_ci return "<illegal>"; 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ci return ""; 100cb93a386Sopenharmony_ci} 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_cistatic const char* coeff_string(GrBlendCoeff coeff) { 103cb93a386Sopenharmony_ci switch (coeff) { 104cb93a386Sopenharmony_ci case kZero_GrBlendCoeff: 105cb93a386Sopenharmony_ci return "zero"; 106cb93a386Sopenharmony_ci case kOne_GrBlendCoeff: 107cb93a386Sopenharmony_ci return "one"; 108cb93a386Sopenharmony_ci case kSC_GrBlendCoeff: 109cb93a386Sopenharmony_ci return "src_color"; 110cb93a386Sopenharmony_ci case kISC_GrBlendCoeff: 111cb93a386Sopenharmony_ci return "inv_src_color"; 112cb93a386Sopenharmony_ci case kDC_GrBlendCoeff: 113cb93a386Sopenharmony_ci return "dst_color"; 114cb93a386Sopenharmony_ci case kIDC_GrBlendCoeff: 115cb93a386Sopenharmony_ci return "inv_dst_color"; 116cb93a386Sopenharmony_ci case kSA_GrBlendCoeff: 117cb93a386Sopenharmony_ci return "src_alpha"; 118cb93a386Sopenharmony_ci case kISA_GrBlendCoeff: 119cb93a386Sopenharmony_ci return "inv_src_alpha"; 120cb93a386Sopenharmony_ci case kDA_GrBlendCoeff: 121cb93a386Sopenharmony_ci return "dst_alpha"; 122cb93a386Sopenharmony_ci case kIDA_GrBlendCoeff: 123cb93a386Sopenharmony_ci return "inv_dst_alpha"; 124cb93a386Sopenharmony_ci case kConstC_GrBlendCoeff: 125cb93a386Sopenharmony_ci return "const_color"; 126cb93a386Sopenharmony_ci case kIConstC_GrBlendCoeff: 127cb93a386Sopenharmony_ci return "inv_const_color"; 128cb93a386Sopenharmony_ci case kS2C_GrBlendCoeff: 129cb93a386Sopenharmony_ci return "src2_color"; 130cb93a386Sopenharmony_ci case kIS2C_GrBlendCoeff: 131cb93a386Sopenharmony_ci return "inv_src2_color"; 132cb93a386Sopenharmony_ci case kS2A_GrBlendCoeff: 133cb93a386Sopenharmony_ci return "src2_alpha"; 134cb93a386Sopenharmony_ci case kIS2A_GrBlendCoeff: 135cb93a386Sopenharmony_ci return "inv_src2_alpha"; 136cb93a386Sopenharmony_ci case kIllegal_GrBlendCoeff: 137cb93a386Sopenharmony_ci SkASSERT(false); 138cb93a386Sopenharmony_ci return "<illegal>"; 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci return ""; 141cb93a386Sopenharmony_ci} 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ciSkString GrXferProcessor::BlendInfo::dump() const { 144cb93a386Sopenharmony_ci SkString out; 145cb93a386Sopenharmony_ci out.printf("write_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)", 146cb93a386Sopenharmony_ci fWriteColor, equation_string(fEquation), coeff_string(fSrcBlend), 147cb93a386Sopenharmony_ci coeff_string(fDstBlend), fBlendConstant.toBytes_RGBA()); 148cb93a386Sopenharmony_ci return out; 149cb93a386Sopenharmony_ci} 150cb93a386Sopenharmony_ci#endif 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 153cb93a386Sopenharmony_ci 154cb93a386Sopenharmony_ciGrXPFactory::AnalysisProperties GrXPFactory::GetAnalysisProperties( 155cb93a386Sopenharmony_ci const GrXPFactory* factory, 156cb93a386Sopenharmony_ci const GrProcessorAnalysisColor& color, 157cb93a386Sopenharmony_ci const GrProcessorAnalysisCoverage& coverage, 158cb93a386Sopenharmony_ci const GrCaps& caps, 159cb93a386Sopenharmony_ci GrClampType clampType) { 160cb93a386Sopenharmony_ci AnalysisProperties result; 161cb93a386Sopenharmony_ci if (factory) { 162cb93a386Sopenharmony_ci result = factory->analysisProperties(color, coverage, caps, clampType); 163cb93a386Sopenharmony_ci } else { 164cb93a386Sopenharmony_ci result = GrPorterDuffXPFactory::SrcOverAnalysisProperties(color, coverage, caps, clampType); 165cb93a386Sopenharmony_ci } 166cb93a386Sopenharmony_ci if (coverage == GrProcessorAnalysisCoverage::kNone) { 167cb93a386Sopenharmony_ci result |= AnalysisProperties::kCompatibleWithCoverageAsAlpha; 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci SkASSERT(!(result & AnalysisProperties::kRequiresDstTexture)); 170cb93a386Sopenharmony_ci if ((result & AnalysisProperties::kReadsDstInShader) && 171cb93a386Sopenharmony_ci !caps.shaderCaps()->dstReadInShaderSupport()) { 172cb93a386Sopenharmony_ci result |= AnalysisProperties::kRequiresDstTexture | 173cb93a386Sopenharmony_ci AnalysisProperties::kRequiresNonOverlappingDraws; 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci return result; 176cb93a386Sopenharmony_ci} 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_cisk_sp<const GrXferProcessor> GrXPFactory::MakeXferProcessor(const GrXPFactory* factory, 179cb93a386Sopenharmony_ci const GrProcessorAnalysisColor& color, 180cb93a386Sopenharmony_ci GrProcessorAnalysisCoverage coverage, 181cb93a386Sopenharmony_ci const GrCaps& caps, 182cb93a386Sopenharmony_ci GrClampType clampType) { 183cb93a386Sopenharmony_ci if (factory) { 184cb93a386Sopenharmony_ci return factory->makeXferProcessor(color, coverage, caps, clampType); 185cb93a386Sopenharmony_ci } else { 186cb93a386Sopenharmony_ci return GrPorterDuffXPFactory::MakeSrcOverXferProcessor(color, coverage, caps); 187cb93a386Sopenharmony_ci } 188cb93a386Sopenharmony_ci} 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////// 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_ciusing ProgramImpl = GrXferProcessor::ProgramImpl; 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci// This is only called for cases where we are doing LCD coverage and not using in shader blending. 195cb93a386Sopenharmony_ci// For these cases we assume the the src alpha is 1, thus we can just use the max for the alpha 196cb93a386Sopenharmony_ci// coverage since src alpha will always be greater than or equal to dst alpha. 197cb93a386Sopenharmony_cistatic void adjust_for_lcd_coverage(GrGLSLXPFragmentBuilder* fragBuilder, 198cb93a386Sopenharmony_ci const char* srcCoverage, 199cb93a386Sopenharmony_ci const GrXferProcessor& proc) { 200cb93a386Sopenharmony_ci if (srcCoverage && proc.isLCD()) { 201cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s.a = max(max(%s.r, %s.g), %s.b);", 202cb93a386Sopenharmony_ci srcCoverage, 203cb93a386Sopenharmony_ci srcCoverage, 204cb93a386Sopenharmony_ci srcCoverage, 205cb93a386Sopenharmony_ci srcCoverage); 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci} 208cb93a386Sopenharmony_ci 209cb93a386Sopenharmony_civoid ProgramImpl::emitCode(const EmitArgs& args) { 210cb93a386Sopenharmony_ci if (!args.fXP.willReadDstColor()) { 211cb93a386Sopenharmony_ci adjust_for_lcd_coverage(args.fXPFragBuilder, args.fInputCoverage, args.fXP); 212cb93a386Sopenharmony_ci this->emitOutputsForBlendState(args); 213cb93a386Sopenharmony_ci } else { 214cb93a386Sopenharmony_ci GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 215cb93a386Sopenharmony_ci GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 216cb93a386Sopenharmony_ci const char* dstColor = fragBuilder->dstColor(); 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci bool needsLocalOutColor = false; 219cb93a386Sopenharmony_ci 220cb93a386Sopenharmony_ci if (args.fDstTextureSamplerHandle.isValid()) { 221cb93a386Sopenharmony_ci if (args.fInputCoverage) { 222cb93a386Sopenharmony_ci // We don't think any shaders actually output negative coverage, but just as a 223cb93a386Sopenharmony_ci // safety check for floating point precision errors, we compare with <= here. We 224cb93a386Sopenharmony_ci // just check the RGB values of the coverage, since the alpha may not have been set 225cb93a386Sopenharmony_ci // when using LCD. If we are using single-channel coverage, alpha will be equal to 226cb93a386Sopenharmony_ci // RGB anyway. 227cb93a386Sopenharmony_ci // 228cb93a386Sopenharmony_ci // The discard here also helps for batching text-draws together, which need to read 229cb93a386Sopenharmony_ci // from a dst copy for blends. However, this only helps the case where the outer 230cb93a386Sopenharmony_ci // bounding boxes of each letter overlap and not two actually parts of the text. 231cb93a386Sopenharmony_ci fragBuilder->codeAppendf("if (all(lessThanEqual(%s.rgb, half3(0)))) {" 232cb93a386Sopenharmony_ci " discard;" 233cb93a386Sopenharmony_ci "}", 234cb93a386Sopenharmony_ci args.fInputCoverage); 235cb93a386Sopenharmony_ci } 236cb93a386Sopenharmony_ci } else { 237cb93a386Sopenharmony_ci needsLocalOutColor = args.fShaderCaps->requiresLocalOutputColorForFBFetch(); 238cb93a386Sopenharmony_ci } 239cb93a386Sopenharmony_ci 240cb93a386Sopenharmony_ci const char* outColor = "_localColorOut"; 241cb93a386Sopenharmony_ci if (!needsLocalOutColor) { 242cb93a386Sopenharmony_ci outColor = args.fOutputPrimary; 243cb93a386Sopenharmony_ci } else { 244cb93a386Sopenharmony_ci fragBuilder->codeAppendf("half4 %s;", outColor); 245cb93a386Sopenharmony_ci } 246cb93a386Sopenharmony_ci 247cb93a386Sopenharmony_ci this->emitBlendCodeForDstRead(fragBuilder, 248cb93a386Sopenharmony_ci uniformHandler, 249cb93a386Sopenharmony_ci args.fInputColor, 250cb93a386Sopenharmony_ci args.fInputCoverage, 251cb93a386Sopenharmony_ci dstColor, 252cb93a386Sopenharmony_ci outColor, 253cb93a386Sopenharmony_ci args.fOutputSecondary, 254cb93a386Sopenharmony_ci args.fXP); 255cb93a386Sopenharmony_ci if (needsLocalOutColor) { 256cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, outColor); 257cb93a386Sopenharmony_ci } 258cb93a386Sopenharmony_ci } 259cb93a386Sopenharmony_ci 260cb93a386Sopenharmony_ci // Swizzle the fragment shader outputs if necessary. 261cb93a386Sopenharmony_ci this->emitWriteSwizzle(args.fXPFragBuilder, 262cb93a386Sopenharmony_ci args.fWriteSwizzle, 263cb93a386Sopenharmony_ci args.fOutputPrimary, 264cb93a386Sopenharmony_ci args.fOutputSecondary); 265cb93a386Sopenharmony_ci} 266cb93a386Sopenharmony_ci 267cb93a386Sopenharmony_civoid ProgramImpl::emitWriteSwizzle(GrGLSLXPFragmentBuilder* x, 268cb93a386Sopenharmony_ci const GrSwizzle& swizzle, 269cb93a386Sopenharmony_ci const char* outColor, 270cb93a386Sopenharmony_ci const char* outColorSecondary) const { 271cb93a386Sopenharmony_ci if (GrSwizzle::RGBA() != swizzle) { 272cb93a386Sopenharmony_ci x->codeAppendf("%s = %s.%s;", outColor, outColor, swizzle.asString().c_str()); 273cb93a386Sopenharmony_ci if (outColorSecondary) { 274cb93a386Sopenharmony_ci x->codeAppendf("%s = %s.%s;", 275cb93a386Sopenharmony_ci outColorSecondary, 276cb93a386Sopenharmony_ci outColorSecondary, 277cb93a386Sopenharmony_ci swizzle.asString().c_str()); 278cb93a386Sopenharmony_ci } 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci} 281cb93a386Sopenharmony_ci 282cb93a386Sopenharmony_civoid ProgramImpl::setData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) { 283cb93a386Sopenharmony_ci this->onSetData(pdm, xp); 284cb93a386Sopenharmony_ci} 285cb93a386Sopenharmony_ci 286cb93a386Sopenharmony_civoid ProgramImpl::DefaultCoverageModulation(GrGLSLXPFragmentBuilder* fragBuilder, 287cb93a386Sopenharmony_ci const char* srcCoverage, 288cb93a386Sopenharmony_ci const char* dstColor, 289cb93a386Sopenharmony_ci const char* outColor, 290cb93a386Sopenharmony_ci const char* outColorSecondary, 291cb93a386Sopenharmony_ci const GrXferProcessor& proc) { 292cb93a386Sopenharmony_ci if (srcCoverage) { 293cb93a386Sopenharmony_ci if (proc.isLCD()) { 294cb93a386Sopenharmony_ci fragBuilder->codeAppendf("half3 lerpRGB = mix(%s.aaa, %s.aaa, %s.rgb);", 295cb93a386Sopenharmony_ci dstColor, 296cb93a386Sopenharmony_ci outColor, 297cb93a386Sopenharmony_ci srcCoverage); 298cb93a386Sopenharmony_ci } 299cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = %s * %s + (half4(1.0) - %s) * %s;", 300cb93a386Sopenharmony_ci outColor, 301cb93a386Sopenharmony_ci srcCoverage, 302cb93a386Sopenharmony_ci outColor, 303cb93a386Sopenharmony_ci srcCoverage, 304cb93a386Sopenharmony_ci dstColor); 305cb93a386Sopenharmony_ci if (proc.isLCD()) { 306cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s.a = max(max(lerpRGB.r, lerpRGB.b), lerpRGB.g);", outColor); 307cb93a386Sopenharmony_ci } 308cb93a386Sopenharmony_ci } 309cb93a386Sopenharmony_ci} 310