|  | /* | 
|  | * Copyright 2015 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "GrXferProcessor.h" | 
|  | #include "GrPipeline.h" | 
|  | #include "gl/GrGLCaps.h" | 
|  |  | 
|  | GrXferProcessor::GrXferProcessor() | 
|  | : fWillReadDstColor(false) | 
|  | , fDstReadUsesMixedSamples(false) | 
|  | , fIsLCD(false) {} | 
|  |  | 
|  | GrXferProcessor::GrXferProcessor(bool willReadDstColor, bool hasMixedSamples, | 
|  | GrProcessorAnalysisCoverage coverage) | 
|  | : fWillReadDstColor(willReadDstColor) | 
|  | , fDstReadUsesMixedSamples(willReadDstColor && hasMixedSamples) | 
|  | , fIsLCD(GrProcessorAnalysisCoverage::kLCD == coverage) {} | 
|  |  | 
|  | bool GrXferProcessor::hasSecondaryOutput() const { | 
|  | if (!this->willReadDstColor()) { | 
|  | return this->onHasSecondaryOutput(); | 
|  | } | 
|  | return this->dstReadUsesMixedSamples(); | 
|  | } | 
|  |  | 
|  | void GrXferProcessor::getBlendInfo(BlendInfo* blendInfo) const { | 
|  | blendInfo->reset(); | 
|  | if (!this->willReadDstColor()) { | 
|  | this->onGetBlendInfo(blendInfo); | 
|  | } else if (this->dstReadUsesMixedSamples()) { | 
|  | blendInfo->fDstBlend = kIS2A_GrBlendCoeff; | 
|  | } | 
|  | } | 
|  |  | 
|  | void GrXferProcessor::getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b, | 
|  | const GrSurfaceOrigin* originIfDstTexture) const { | 
|  | uint32_t key = this->willReadDstColor() ? 0x1 : 0x0; | 
|  | if (key) { | 
|  | if (originIfDstTexture) { | 
|  | key |= 0x2; | 
|  | if (kTopLeft_GrSurfaceOrigin == *originIfDstTexture) { | 
|  | key |= 0x4; | 
|  | } | 
|  | } | 
|  | if (this->dstReadUsesMixedSamples()) { | 
|  | key |= 0x8; | 
|  | } | 
|  | } | 
|  | if (fIsLCD) { | 
|  | key |= 0x10; | 
|  | } | 
|  | b->add32(key); | 
|  | this->onGetGLSLProcessorKey(caps, b); | 
|  | } | 
|  |  | 
|  | #ifdef SK_DEBUG | 
|  | static const char* equation_string(GrBlendEquation eq) { | 
|  | switch (eq) { | 
|  | case kAdd_GrBlendEquation: | 
|  | return "add"; | 
|  | case kSubtract_GrBlendEquation: | 
|  | return "subtract"; | 
|  | case kReverseSubtract_GrBlendEquation: | 
|  | return "reverse_subtract"; | 
|  | case kScreen_GrBlendEquation: | 
|  | return "screen"; | 
|  | case kOverlay_GrBlendEquation: | 
|  | return "overlay"; | 
|  | case kDarken_GrBlendEquation: | 
|  | return "darken"; | 
|  | case kLighten_GrBlendEquation: | 
|  | return "lighten"; | 
|  | case kColorDodge_GrBlendEquation: | 
|  | return "color_dodge"; | 
|  | case kColorBurn_GrBlendEquation: | 
|  | return "color_burn"; | 
|  | case kHardLight_GrBlendEquation: | 
|  | return "hard_light"; | 
|  | case kSoftLight_GrBlendEquation: | 
|  | return "soft_light"; | 
|  | case kDifference_GrBlendEquation: | 
|  | return "difference"; | 
|  | case kExclusion_GrBlendEquation: | 
|  | return "exclusion"; | 
|  | case kMultiply_GrBlendEquation: | 
|  | return "multiply"; | 
|  | case kHSLHue_GrBlendEquation: | 
|  | return "hsl_hue"; | 
|  | case kHSLSaturation_GrBlendEquation: | 
|  | return "hsl_saturation"; | 
|  | case kHSLColor_GrBlendEquation: | 
|  | return "hsl_color"; | 
|  | case kHSLLuminosity_GrBlendEquation: | 
|  | return "hsl_luminosity"; | 
|  | }; | 
|  | return ""; | 
|  | } | 
|  |  | 
|  | static const char* coeff_string(GrBlendCoeff coeff) { | 
|  | switch (coeff) { | 
|  | case kZero_GrBlendCoeff: | 
|  | return "zero"; | 
|  | case kOne_GrBlendCoeff: | 
|  | return "one"; | 
|  | case kSC_GrBlendCoeff: | 
|  | return "src_color"; | 
|  | case kISC_GrBlendCoeff: | 
|  | return "inv_src_color"; | 
|  | case kDC_GrBlendCoeff: | 
|  | return "dst_color"; | 
|  | case kIDC_GrBlendCoeff: | 
|  | return "inv_dst_color"; | 
|  | case kSA_GrBlendCoeff: | 
|  | return "src_alpha"; | 
|  | case kISA_GrBlendCoeff: | 
|  | return "inv_src_alpha"; | 
|  | case kDA_GrBlendCoeff: | 
|  | return "dst_alpha"; | 
|  | case kIDA_GrBlendCoeff: | 
|  | return "inv_dst_alpha"; | 
|  | case kConstC_GrBlendCoeff: | 
|  | return "const_color"; | 
|  | case kIConstC_GrBlendCoeff: | 
|  | return "inv_const_color"; | 
|  | case kConstA_GrBlendCoeff: | 
|  | return "const_alpha"; | 
|  | case kIConstA_GrBlendCoeff: | 
|  | return "inv_const_alpha"; | 
|  | case kS2C_GrBlendCoeff: | 
|  | return "src2_color"; | 
|  | case kIS2C_GrBlendCoeff: | 
|  | return "inv_src2_color"; | 
|  | case kS2A_GrBlendCoeff: | 
|  | return "src2_alpha"; | 
|  | case kIS2A_GrBlendCoeff: | 
|  | return "inv_src2_alpha"; | 
|  | } | 
|  | return ""; | 
|  | } | 
|  |  | 
|  | SkString GrXferProcessor::BlendInfo::dump() const { | 
|  | SkString out; | 
|  | out.printf("write_color(%d) equation(%s) src_coeff(%s) dst_coeff:(%s) const(0x%08x)", | 
|  | fWriteColor, equation_string(fEquation), coeff_string(fSrcBlend), | 
|  | coeff_string(fDstBlend), fBlendConstant); | 
|  | return out; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | GrXPFactory::AnalysisProperties GrXPFactory::GetAnalysisProperties( | 
|  | const GrXPFactory* factory, | 
|  | const GrProcessorAnalysisColor& color, | 
|  | const GrProcessorAnalysisCoverage& coverage, | 
|  | const GrCaps& caps) { | 
|  | AnalysisProperties result; | 
|  | if (factory) { | 
|  | result = factory->analysisProperties(color, coverage, caps); | 
|  | } else { | 
|  | result = GrPorterDuffXPFactory::SrcOverAnalysisProperties(color, coverage, caps); | 
|  | } | 
|  | SkASSERT(!(result & AnalysisProperties::kRequiresDstTexture)); | 
|  | if ((result & AnalysisProperties::kReadsDstInShader) && | 
|  | !caps.shaderCaps()->dstReadInShaderSupport()) { | 
|  | result |= AnalysisProperties::kRequiresDstTexture; | 
|  | if (caps.textureBarrierSupport()) { | 
|  | result |= AnalysisProperties::kRequiresBarrierBetweenOverlappingDraws; | 
|  | } | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | sk_sp<const GrXferProcessor> GrXPFactory::MakeXferProcessor(const GrXPFactory* factory, | 
|  | const GrProcessorAnalysisColor& color, | 
|  | GrProcessorAnalysisCoverage coverage, | 
|  | bool hasMixedSamples, | 
|  | const GrCaps& caps) { | 
|  | SkASSERT(!hasMixedSamples || caps.shaderCaps()->dualSourceBlendingSupport()); | 
|  | if (factory) { | 
|  | return factory->makeXferProcessor(color, coverage, hasMixedSamples, caps); | 
|  | } else { | 
|  | return GrPorterDuffXPFactory::MakeSrcOverXferProcessor(color, coverage, hasMixedSamples, | 
|  | caps); | 
|  | } | 
|  | } |