1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 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/effects/GrPorterDuffXferProcessor.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/gpu/GrTypes.h" 11cb93a386Sopenharmony_ci#include "include/private/SkMacros.h" 12cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 13cb93a386Sopenharmony_ci#include "src/gpu/GrBlend.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrPipeline.h" 16cb93a386Sopenharmony_ci#include "src/gpu/GrProcessor.h" 17cb93a386Sopenharmony_ci#include "src/gpu/GrProcessorAnalysis.h" 18cb93a386Sopenharmony_ci#include "src/gpu/GrXferProcessor.h" 19cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLBlend.h" 20cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h" 21cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLProgramDataManager.h" 22cb93a386Sopenharmony_ci#include "src/gpu/glsl/GrGLSLUniformHandler.h" 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ci/** 25cb93a386Sopenharmony_ci * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage. 26cb93a386Sopenharmony_ci */ 27cb93a386Sopenharmony_ciclass BlendFormula { 28cb93a386Sopenharmony_cipublic: 29cb93a386Sopenharmony_ci /** 30cb93a386Sopenharmony_ci * Values the shader can write to primary and secondary outputs. These are all modulated by 31cb93a386Sopenharmony_ci * coverage. The XP will ignore the multiplies when not using coverage. 32cb93a386Sopenharmony_ci */ 33cb93a386Sopenharmony_ci enum OutputType { 34cb93a386Sopenharmony_ci kNone_OutputType, //<! 0 35cb93a386Sopenharmony_ci kCoverage_OutputType, //<! inputCoverage 36cb93a386Sopenharmony_ci kModulate_OutputType, //<! inputColor * inputCoverage 37cb93a386Sopenharmony_ci kSAModulate_OutputType, //<! inputColor.a * inputCoverage 38cb93a386Sopenharmony_ci kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage 39cb93a386Sopenharmony_ci kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci kLast_OutputType = kISCModulate_OutputType 42cb93a386Sopenharmony_ci }; 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci constexpr BlendFormula(OutputType primaryOut, OutputType secondaryOut, GrBlendEquation equation, 45cb93a386Sopenharmony_ci GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) 46cb93a386Sopenharmony_ci : fPrimaryOutputType(primaryOut) 47cb93a386Sopenharmony_ci , fSecondaryOutputType(secondaryOut) 48cb93a386Sopenharmony_ci , fBlendEquation(equation) 49cb93a386Sopenharmony_ci , fSrcCoeff(srcCoeff) 50cb93a386Sopenharmony_ci , fDstCoeff(dstCoeff) 51cb93a386Sopenharmony_ci , fProps(GetProperties(primaryOut, secondaryOut, equation, srcCoeff, dstCoeff)) {} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci BlendFormula(const BlendFormula&) = default; 54cb93a386Sopenharmony_ci BlendFormula& operator=(const BlendFormula&) = default; 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci bool operator==(const BlendFormula& that) const { 57cb93a386Sopenharmony_ci return fPrimaryOutputType == that.fPrimaryOutputType && 58cb93a386Sopenharmony_ci fSecondaryOutputType == that. fSecondaryOutputType && 59cb93a386Sopenharmony_ci fBlendEquation == that.fBlendEquation && 60cb93a386Sopenharmony_ci fSrcCoeff == that.fSrcCoeff && 61cb93a386Sopenharmony_ci fDstCoeff == that.fDstCoeff && 62cb93a386Sopenharmony_ci fProps == that.fProps; 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci bool hasSecondaryOutput() const { 66cb93a386Sopenharmony_ci return kNone_OutputType != fSecondaryOutputType; 67cb93a386Sopenharmony_ci } 68cb93a386Sopenharmony_ci bool modifiesDst() const { 69cb93a386Sopenharmony_ci return SkToBool(fProps & kModifiesDst_Property); 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci bool unaffectedByDst() const { 72cb93a386Sopenharmony_ci return SkToBool(fProps & kUnaffectedByDst_Property); 73cb93a386Sopenharmony_ci } 74cb93a386Sopenharmony_ci // We don't always fully optimize the blend formula (e.g., for opaque src-over), so we include 75cb93a386Sopenharmony_ci // an "IfOpaque" variant to help set AnalysisProperties::kUnaffectedByDstValue in those cases. 76cb93a386Sopenharmony_ci bool unaffectedByDstIfOpaque() const { 77cb93a386Sopenharmony_ci return SkToBool(fProps & kUnaffectedByDstIfOpaque_Property); 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci bool usesInputColor() const { 80cb93a386Sopenharmony_ci return SkToBool(fProps & kUsesInputColor_Property); 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci bool canTweakAlphaForCoverage() const { 83cb93a386Sopenharmony_ci return SkToBool(fProps & kCanTweakAlphaForCoverage_Property); 84cb93a386Sopenharmony_ci } 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci GrBlendEquation equation() const { 87cb93a386Sopenharmony_ci return fBlendEquation; 88cb93a386Sopenharmony_ci } 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci GrBlendCoeff srcCoeff() const { 91cb93a386Sopenharmony_ci return fSrcCoeff; 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci GrBlendCoeff dstCoeff() const { 95cb93a386Sopenharmony_ci return fDstCoeff; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci OutputType primaryOutput() const { 99cb93a386Sopenharmony_ci return fPrimaryOutputType; 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci 102cb93a386Sopenharmony_ci OutputType secondaryOutput() const { 103cb93a386Sopenharmony_ci return fSecondaryOutputType; 104cb93a386Sopenharmony_ci } 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_ciprivate: 107cb93a386Sopenharmony_ci enum Properties { 108cb93a386Sopenharmony_ci kModifiesDst_Property = 1 << 0, 109cb93a386Sopenharmony_ci kUnaffectedByDst_Property = 1 << 1, 110cb93a386Sopenharmony_ci kUnaffectedByDstIfOpaque_Property = 1 << 2, 111cb93a386Sopenharmony_ci kUsesInputColor_Property = 1 << 3, 112cb93a386Sopenharmony_ci kCanTweakAlphaForCoverage_Property = 1 << 4, 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ci kLast_Property = kCanTweakAlphaForCoverage_Property 115cb93a386Sopenharmony_ci }; 116cb93a386Sopenharmony_ci SK_DECL_BITFIELD_OPS_FRIENDS(Properties) 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci /** 119cb93a386Sopenharmony_ci * Deduce the properties of a BlendFormula. 120cb93a386Sopenharmony_ci */ 121cb93a386Sopenharmony_ci static constexpr Properties GetProperties(OutputType PrimaryOut, OutputType SecondaryOut, 122cb93a386Sopenharmony_ci GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, 123cb93a386Sopenharmony_ci GrBlendCoeff DstCoeff); 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci struct { 126cb93a386Sopenharmony_ci // We allot the enums one more bit than they require because MSVC seems to sign-extend 127cb93a386Sopenharmony_ci // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4) 128cb93a386Sopenharmony_ci OutputType fPrimaryOutputType : 4; 129cb93a386Sopenharmony_ci OutputType fSecondaryOutputType : 4; 130cb93a386Sopenharmony_ci GrBlendEquation fBlendEquation : 6; 131cb93a386Sopenharmony_ci GrBlendCoeff fSrcCoeff : 6; 132cb93a386Sopenharmony_ci GrBlendCoeff fDstCoeff : 6; 133cb93a386Sopenharmony_ci Properties fProps : 32 - (4 + 4 + 6 + 6 + 6); 134cb93a386Sopenharmony_ci }; 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci static_assert(kLast_OutputType < (1 << 3)); 137cb93a386Sopenharmony_ci static_assert(kLast_GrBlendEquation < (1 << 5)); 138cb93a386Sopenharmony_ci static_assert(kLast_GrBlendCoeff < (1 << 5)); 139cb93a386Sopenharmony_ci static_assert(kLast_Property < (1 << 6)); 140cb93a386Sopenharmony_ci}; 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_cistatic_assert(4 == sizeof(BlendFormula)); 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ciSK_MAKE_BITFIELD_OPS(BlendFormula::Properties) 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ciconstexpr BlendFormula::Properties BlendFormula::GetProperties(OutputType PrimaryOut, 147cb93a386Sopenharmony_ci OutputType SecondaryOut, 148cb93a386Sopenharmony_ci GrBlendEquation BlendEquation, 149cb93a386Sopenharmony_ci GrBlendCoeff SrcCoeff, 150cb93a386Sopenharmony_ci GrBlendCoeff DstCoeff) { 151cb93a386Sopenharmony_ci return 152cb93a386Sopenharmony_ci // The provided formula should already be optimized before a BlendFormula is constructed. 153cb93a386Sopenharmony_ci // Assert that here while setting up the properties in the constexpr constructor. 154cb93a386Sopenharmony_ci SkASSERT((kNone_OutputType == PrimaryOut) == !GrBlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)), 155cb93a386Sopenharmony_ci SkASSERT(!GrBlendCoeffRefsSrc2(SrcCoeff)), 156cb93a386Sopenharmony_ci SkASSERT((kNone_OutputType == SecondaryOut) == !GrBlendCoeffRefsSrc2(DstCoeff)), 157cb93a386Sopenharmony_ci SkASSERT(PrimaryOut != SecondaryOut || kNone_OutputType == PrimaryOut), 158cb93a386Sopenharmony_ci SkASSERT(kNone_OutputType != PrimaryOut || kNone_OutputType == SecondaryOut), 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci static_cast<Properties>( 161cb93a386Sopenharmony_ci (GrBlendModifiesDst(BlendEquation, SrcCoeff, DstCoeff) ? kModifiesDst_Property : 0) | 162cb93a386Sopenharmony_ci (!GrBlendCoeffsUseDstColor(SrcCoeff, DstCoeff, false/*srcColorIsOpaque*/) 163cb93a386Sopenharmony_ci ? kUnaffectedByDst_Property 164cb93a386Sopenharmony_ci : 0) | 165cb93a386Sopenharmony_ci (!GrBlendCoeffsUseDstColor(SrcCoeff, DstCoeff, true/*srcColorIsOpaque*/) 166cb93a386Sopenharmony_ci ? kUnaffectedByDstIfOpaque_Property 167cb93a386Sopenharmony_ci : 0) | 168cb93a386Sopenharmony_ci ((PrimaryOut >= kModulate_OutputType && GrBlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)) || 169cb93a386Sopenharmony_ci (SecondaryOut >= kModulate_OutputType && 170cb93a386Sopenharmony_ci GrBlendCoeffRefsSrc2(DstCoeff)) 171cb93a386Sopenharmony_ci ? kUsesInputColor_Property 172cb93a386Sopenharmony_ci : 0) | // We assert later that SrcCoeff doesn't ref src2. 173cb93a386Sopenharmony_ci ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) && 174cb93a386Sopenharmony_ci kNone_OutputType == SecondaryOut && 175cb93a386Sopenharmony_ci GrBlendAllowsCoverageAsAlpha(BlendEquation, SrcCoeff, DstCoeff) 176cb93a386Sopenharmony_ci ? kCanTweakAlphaForCoverage_Property 177cb93a386Sopenharmony_ci : 0)); 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci/** 181cb93a386Sopenharmony_ci * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard 182cb93a386Sopenharmony_ci * Porter Duff formula. 183cb93a386Sopenharmony_ci */ 184cb93a386Sopenharmony_cistatic constexpr BlendFormula MakeCoeffFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 185cb93a386Sopenharmony_ci // When the coeffs are (Zero, Zero) or (Zero, One) we set the primary output to none. 186cb93a386Sopenharmony_ci return (kZero_GrBlendCoeff == srcCoeff && 187cb93a386Sopenharmony_ci (kZero_GrBlendCoeff == dstCoeff || kOne_GrBlendCoeff == dstCoeff)) 188cb93a386Sopenharmony_ci ? BlendFormula(BlendFormula::kNone_OutputType, BlendFormula::kNone_OutputType, 189cb93a386Sopenharmony_ci kAdd_GrBlendEquation, kZero_GrBlendCoeff, dstCoeff) 190cb93a386Sopenharmony_ci : BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kNone_OutputType, 191cb93a386Sopenharmony_ci kAdd_GrBlendEquation, srcCoeff, dstCoeff); 192cb93a386Sopenharmony_ci} 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci/** 195cb93a386Sopenharmony_ci * Basic coeff formula similar to MakeCoeffFormula but we will make the src f*Sa. This is used in 196cb93a386Sopenharmony_ci * LCD dst-out. 197cb93a386Sopenharmony_ci */ 198cb93a386Sopenharmony_cistatic constexpr BlendFormula MakeSAModulateFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 199cb93a386Sopenharmony_ci return BlendFormula(BlendFormula::kSAModulate_OutputType, BlendFormula::kNone_OutputType, 200cb93a386Sopenharmony_ci kAdd_GrBlendEquation, srcCoeff, dstCoeff); 201cb93a386Sopenharmony_ci} 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_ci/** 204cb93a386Sopenharmony_ci * When there is coverage, the equation with f=coverage is: 205cb93a386Sopenharmony_ci * 206cb93a386Sopenharmony_ci * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D 207cb93a386Sopenharmony_ci * 208cb93a386Sopenharmony_ci * This can be rewritten as: 209cb93a386Sopenharmony_ci * 210cb93a386Sopenharmony_ci * D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)]) 211cb93a386Sopenharmony_ci * 212cb93a386Sopenharmony_ci * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the 213cb93a386Sopenharmony_ci * HW dst coeff with IS2C. 214cb93a386Sopenharmony_ci * 215cb93a386Sopenharmony_ci * Xfer modes: dst-atop (Sa!=1) 216cb93a386Sopenharmony_ci */ 217cb93a386Sopenharmony_cistatic constexpr BlendFormula MakeCoverageFormula( 218cb93a386Sopenharmony_ci BlendFormula::OutputType oneMinusDstCoeffModulateOutput, GrBlendCoeff srcCoeff) { 219cb93a386Sopenharmony_ci return BlendFormula(BlendFormula::kModulate_OutputType, oneMinusDstCoeffModulateOutput, 220cb93a386Sopenharmony_ci kAdd_GrBlendEquation, srcCoeff, kIS2C_GrBlendCoeff); 221cb93a386Sopenharmony_ci} 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_ci/** 224cb93a386Sopenharmony_ci * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes: 225cb93a386Sopenharmony_ci * 226cb93a386Sopenharmony_ci * D' = f * D * dstCoeff + (1-f) * D 227cb93a386Sopenharmony_ci * 228cb93a386Sopenharmony_ci * This can be rewritten as: 229cb93a386Sopenharmony_ci * 230cb93a386Sopenharmony_ci * D' = D - D * [f * (1 - dstCoeff)] 231cb93a386Sopenharmony_ci * 232cb93a386Sopenharmony_ci * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse 233cb93a386Sopenharmony_ci * subtract HW blend equation with coeffs of (DC, One). 234cb93a386Sopenharmony_ci * 235cb93a386Sopenharmony_ci * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1) 236cb93a386Sopenharmony_ci */ 237cb93a386Sopenharmony_cistatic constexpr BlendFormula MakeCoverageSrcCoeffZeroFormula( 238cb93a386Sopenharmony_ci BlendFormula::OutputType oneMinusDstCoeffModulateOutput) { 239cb93a386Sopenharmony_ci return BlendFormula(oneMinusDstCoeffModulateOutput, BlendFormula::kNone_OutputType, 240cb93a386Sopenharmony_ci kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff); 241cb93a386Sopenharmony_ci} 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci/** 244cb93a386Sopenharmony_ci * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes: 245cb93a386Sopenharmony_ci * 246cb93a386Sopenharmony_ci * D' = f * S * srcCoeff + (1-f) * D 247cb93a386Sopenharmony_ci * 248cb93a386Sopenharmony_ci * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff 249cb93a386Sopenharmony_ci * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.) 250cb93a386Sopenharmony_ci * 251cb93a386Sopenharmony_ci * Xfer modes (Sa!=1): src, src-in, src-out 252cb93a386Sopenharmony_ci */ 253cb93a386Sopenharmony_cistatic constexpr BlendFormula MakeCoverageDstCoeffZeroFormula(GrBlendCoeff srcCoeff) { 254cb93a386Sopenharmony_ci return BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kCoverage_OutputType, 255cb93a386Sopenharmony_ci kAdd_GrBlendEquation, srcCoeff, kIS2A_GrBlendCoeff); 256cb93a386Sopenharmony_ci} 257cb93a386Sopenharmony_ci 258cb93a386Sopenharmony_ci/** 259cb93a386Sopenharmony_ci * This table outlines the blend formulas we will use with each xfermode, with and without coverage, 260cb93a386Sopenharmony_ci * with and without an opaque input color. Optimization properties are deduced at compile time so we 261cb93a386Sopenharmony_ci * can make runtime decisions quickly. RGB coverage is not supported. 262cb93a386Sopenharmony_ci */ 263cb93a386Sopenharmony_cistatic constexpr BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = { 264cb93a386Sopenharmony_ci /*>> No coverage, input color unknown <<*/ {{ 265cb93a386Sopenharmony_ci 266cb93a386Sopenharmony_ci /* clear */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 267cb93a386Sopenharmony_ci /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kZero_GrBlendCoeff), 268cb93a386Sopenharmony_ci /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 269cb93a386Sopenharmony_ci /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 270cb93a386Sopenharmony_ci /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 271cb93a386Sopenharmony_ci /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 272cb93a386Sopenharmony_ci /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kSA_GrBlendCoeff), 273cb93a386Sopenharmony_ci /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 274cb93a386Sopenharmony_ci /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff), 275cb93a386Sopenharmony_ci /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 276cb93a386Sopenharmony_ci /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kSA_GrBlendCoeff), 277cb93a386Sopenharmony_ci /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 278cb93a386Sopenharmony_ci /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 279cb93a386Sopenharmony_ci /* modulate */ MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff), 280cb93a386Sopenharmony_ci /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 281cb93a386Sopenharmony_ci 282cb93a386Sopenharmony_ci }, /*>> Has coverage, input color unknown <<*/ { 283cb93a386Sopenharmony_ci 284cb93a386Sopenharmony_ci /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 285cb93a386Sopenharmony_ci /* src */ MakeCoverageDstCoeffZeroFormula(kOne_GrBlendCoeff), 286cb93a386Sopenharmony_ci /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 287cb93a386Sopenharmony_ci /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 288cb93a386Sopenharmony_ci /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 289cb93a386Sopenharmony_ci /* src-in */ MakeCoverageDstCoeffZeroFormula(kDA_GrBlendCoeff), 290cb93a386Sopenharmony_ci /* dst-in */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType), 291cb93a386Sopenharmony_ci /* src-out */ MakeCoverageDstCoeffZeroFormula(kIDA_GrBlendCoeff), 292cb93a386Sopenharmony_ci /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff), 293cb93a386Sopenharmony_ci /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 294cb93a386Sopenharmony_ci /* dst-atop */ MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), 295cb93a386Sopenharmony_ci /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 296cb93a386Sopenharmony_ci /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 297cb93a386Sopenharmony_ci /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 298cb93a386Sopenharmony_ci /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 299cb93a386Sopenharmony_ci 300cb93a386Sopenharmony_ci }}, /*>> No coverage, input color opaque <<*/ {{ 301cb93a386Sopenharmony_ci 302cb93a386Sopenharmony_ci /* clear */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 303cb93a386Sopenharmony_ci /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kZero_GrBlendCoeff), 304cb93a386Sopenharmony_ci /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 305cb93a386Sopenharmony_ci /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), // see comment below 306cb93a386Sopenharmony_ci /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 307cb93a386Sopenharmony_ci /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 308cb93a386Sopenharmony_ci /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 309cb93a386Sopenharmony_ci /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 310cb93a386Sopenharmony_ci /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 311cb93a386Sopenharmony_ci /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 312cb93a386Sopenharmony_ci /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 313cb93a386Sopenharmony_ci /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 314cb93a386Sopenharmony_ci /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 315cb93a386Sopenharmony_ci /* modulate */ MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff), 316cb93a386Sopenharmony_ci /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 317cb93a386Sopenharmony_ci 318cb93a386Sopenharmony_ci }, /*>> Has coverage, input color opaque <<*/ { 319cb93a386Sopenharmony_ci 320cb93a386Sopenharmony_ci /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 321cb93a386Sopenharmony_ci /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 322cb93a386Sopenharmony_ci /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 323cb93a386Sopenharmony_ci /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 324cb93a386Sopenharmony_ci /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 325cb93a386Sopenharmony_ci /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 326cb93a386Sopenharmony_ci /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 327cb93a386Sopenharmony_ci /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 328cb93a386Sopenharmony_ci /* dst-out */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 329cb93a386Sopenharmony_ci /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 330cb93a386Sopenharmony_ci /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 331cb93a386Sopenharmony_ci /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 332cb93a386Sopenharmony_ci /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 333cb93a386Sopenharmony_ci /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 334cb93a386Sopenharmony_ci /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 335cb93a386Sopenharmony_ci}}}; 336cb93a386Sopenharmony_ci// In the above table src-over is not optimized to src mode when the color is opaque because we 337cb93a386Sopenharmony_ci// found no advantage to doing so. Also, we are using a global src-over XP in most cases which is 338cb93a386Sopenharmony_ci// not specialized for opaque input. For GPUs where dropping to src (and thus able to disable 339cb93a386Sopenharmony_ci// blending) is an advantage we change the blend mode to src before getitng the blend formula from 340cb93a386Sopenharmony_ci// this table. 341cb93a386Sopenharmony_cistatic constexpr BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = { 342cb93a386Sopenharmony_ci /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 343cb93a386Sopenharmony_ci /* src */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff), 344cb93a386Sopenharmony_ci /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 345cb93a386Sopenharmony_ci /* src-over */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff), 346cb93a386Sopenharmony_ci /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 347cb93a386Sopenharmony_ci /* src-in */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff), 348cb93a386Sopenharmony_ci /* dst-in */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType), 349cb93a386Sopenharmony_ci /* src-out */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff), 350cb93a386Sopenharmony_ci /* dst-out */ MakeSAModulateFormula(kZero_GrBlendCoeff, kISC_GrBlendCoeff), 351cb93a386Sopenharmony_ci /* src-atop */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff), 352cb93a386Sopenharmony_ci /* dst-atop */ MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), 353cb93a386Sopenharmony_ci /* xor */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff), 354cb93a386Sopenharmony_ci /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 355cb93a386Sopenharmony_ci /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 356cb93a386Sopenharmony_ci /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 357cb93a386Sopenharmony_ci}; 358cb93a386Sopenharmony_ci 359cb93a386Sopenharmony_cistatic BlendFormula get_blend_formula(bool isOpaque, 360cb93a386Sopenharmony_ci bool hasCoverage, 361cb93a386Sopenharmony_ci SkBlendMode xfermode) { 362cb93a386Sopenharmony_ci SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode); 363cb93a386Sopenharmony_ci return gBlendTable[isOpaque][hasCoverage][(int)xfermode]; 364cb93a386Sopenharmony_ci} 365cb93a386Sopenharmony_ci 366cb93a386Sopenharmony_cistatic BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) { 367cb93a386Sopenharmony_ci SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode); 368cb93a386Sopenharmony_ci 369cb93a386Sopenharmony_ci return gLCDBlendTable[(int)xfermode]; 370cb93a386Sopenharmony_ci} 371cb93a386Sopenharmony_ci 372cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 373cb93a386Sopenharmony_ci 374cb93a386Sopenharmony_ciclass PorterDuffXferProcessor : public GrXferProcessor { 375cb93a386Sopenharmony_cipublic: 376cb93a386Sopenharmony_ci PorterDuffXferProcessor(BlendFormula blendFormula, GrProcessorAnalysisCoverage coverage) 377cb93a386Sopenharmony_ci : INHERITED(kPorterDuffXferProcessor_ClassID, /*willReadDstColor=*/false, coverage) 378cb93a386Sopenharmony_ci , fBlendFormula(blendFormula) { 379cb93a386Sopenharmony_ci } 380cb93a386Sopenharmony_ci 381cb93a386Sopenharmony_ci const char* name() const override { return "Porter Duff"; } 382cb93a386Sopenharmony_ci 383cb93a386Sopenharmony_ci SkString getShaderDfxInfo() const override; 384cb93a386Sopenharmony_ci 385cb93a386Sopenharmony_ci std::unique_ptr<ProgramImpl> makeProgramImpl() const override; 386cb93a386Sopenharmony_ci 387cb93a386Sopenharmony_ci BlendFormula getBlendFormula() const { return fBlendFormula; } 388cb93a386Sopenharmony_ci 389cb93a386Sopenharmony_ciprivate: 390cb93a386Sopenharmony_ci void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; 391cb93a386Sopenharmony_ci 392cb93a386Sopenharmony_ci bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); } 393cb93a386Sopenharmony_ci 394cb93a386Sopenharmony_ci void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 395cb93a386Sopenharmony_ci blendInfo->fEquation = fBlendFormula.equation(); 396cb93a386Sopenharmony_ci blendInfo->fSrcBlend = fBlendFormula.srcCoeff(); 397cb93a386Sopenharmony_ci blendInfo->fDstBlend = fBlendFormula.dstCoeff(); 398cb93a386Sopenharmony_ci blendInfo->fWriteColor = fBlendFormula.modifiesDst(); 399cb93a386Sopenharmony_ci } 400cb93a386Sopenharmony_ci 401cb93a386Sopenharmony_ci bool onIsEqual(const GrXferProcessor& xpBase) const override { 402cb93a386Sopenharmony_ci const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>(); 403cb93a386Sopenharmony_ci return fBlendFormula == xp.fBlendFormula; 404cb93a386Sopenharmony_ci } 405cb93a386Sopenharmony_ci 406cb93a386Sopenharmony_ci const BlendFormula fBlendFormula; 407cb93a386Sopenharmony_ci 408cb93a386Sopenharmony_ci using INHERITED = GrXferProcessor; 409cb93a386Sopenharmony_ci}; 410cb93a386Sopenharmony_ci 411cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 412cb93a386Sopenharmony_ci 413cb93a386Sopenharmony_cistatic void append_color_output(const PorterDuffXferProcessor& xp, 414cb93a386Sopenharmony_ci GrGLSLXPFragmentBuilder* fragBuilder, 415cb93a386Sopenharmony_ci BlendFormula::OutputType outputType, const char* output, 416cb93a386Sopenharmony_ci const char* inColor, const char* inCoverage) { 417cb93a386Sopenharmony_ci SkASSERT(inCoverage); 418cb93a386Sopenharmony_ci SkASSERT(inColor); 419cb93a386Sopenharmony_ci switch (outputType) { 420cb93a386Sopenharmony_ci case BlendFormula::kNone_OutputType: 421cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = half4(0.0);", output); 422cb93a386Sopenharmony_ci break; 423cb93a386Sopenharmony_ci case BlendFormula::kCoverage_OutputType: 424cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = %s;", output, inCoverage); 425cb93a386Sopenharmony_ci break; 426cb93a386Sopenharmony_ci case BlendFormula::kModulate_OutputType: 427cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage); 428cb93a386Sopenharmony_ci break; 429cb93a386Sopenharmony_ci case BlendFormula::kSAModulate_OutputType: 430cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage); 431cb93a386Sopenharmony_ci break; 432cb93a386Sopenharmony_ci case BlendFormula::kISAModulate_OutputType: 433cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage); 434cb93a386Sopenharmony_ci break; 435cb93a386Sopenharmony_ci case BlendFormula::kISCModulate_OutputType: 436cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = (half4(1.0) - %s) * %s;", output, inColor, inCoverage); 437cb93a386Sopenharmony_ci break; 438cb93a386Sopenharmony_ci default: 439cb93a386Sopenharmony_ci SK_ABORT("Unsupported output type."); 440cb93a386Sopenharmony_ci break; 441cb93a386Sopenharmony_ci } 442cb93a386Sopenharmony_ci} 443cb93a386Sopenharmony_ci 444cb93a386Sopenharmony_ciSkString PorterDuffXferProcessor::getShaderDfxInfo() const 445cb93a386Sopenharmony_ci{ 446cb93a386Sopenharmony_ci SkString format; 447cb93a386Sopenharmony_ci format.printf("ShaderDfx_PorterDuffXfer_%d_%d", fBlendFormula.primaryOutput(), fBlendFormula.secondaryOutput()); 448cb93a386Sopenharmony_ci return format; 449cb93a386Sopenharmony_ci} 450cb93a386Sopenharmony_ci 451cb93a386Sopenharmony_civoid PorterDuffXferProcessor::onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const { 452cb93a386Sopenharmony_ci b->add32(fBlendFormula.primaryOutput() | (fBlendFormula.secondaryOutput() << 3)); 453cb93a386Sopenharmony_ci static_assert(BlendFormula::kLast_OutputType < 8); 454cb93a386Sopenharmony_ci} 455cb93a386Sopenharmony_ci 456cb93a386Sopenharmony_cistd::unique_ptr<GrXferProcessor::ProgramImpl> PorterDuffXferProcessor::makeProgramImpl() const { 457cb93a386Sopenharmony_ci class Impl : public ProgramImpl { 458cb93a386Sopenharmony_ci private: 459cb93a386Sopenharmony_ci void emitOutputsForBlendState(const EmitArgs& args) override { 460cb93a386Sopenharmony_ci const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>(); 461cb93a386Sopenharmony_ci GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 462cb93a386Sopenharmony_ci 463cb93a386Sopenharmony_ci const BlendFormula& blendFormula = xp.fBlendFormula; 464cb93a386Sopenharmony_ci if (blendFormula.hasSecondaryOutput()) { 465cb93a386Sopenharmony_ci append_color_output(xp, 466cb93a386Sopenharmony_ci fragBuilder, 467cb93a386Sopenharmony_ci blendFormula.secondaryOutput(), 468cb93a386Sopenharmony_ci args.fOutputSecondary, 469cb93a386Sopenharmony_ci args.fInputColor, 470cb93a386Sopenharmony_ci args.fInputCoverage); 471cb93a386Sopenharmony_ci } 472cb93a386Sopenharmony_ci append_color_output(xp, 473cb93a386Sopenharmony_ci fragBuilder, 474cb93a386Sopenharmony_ci blendFormula.primaryOutput(), 475cb93a386Sopenharmony_ci args.fOutputPrimary, 476cb93a386Sopenharmony_ci args.fInputColor, 477cb93a386Sopenharmony_ci args.fInputCoverage); 478cb93a386Sopenharmony_ci } 479cb93a386Sopenharmony_ci }; 480cb93a386Sopenharmony_ci 481cb93a386Sopenharmony_ci return std::make_unique<Impl>(); 482cb93a386Sopenharmony_ci} 483cb93a386Sopenharmony_ci 484cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 485cb93a386Sopenharmony_ci 486cb93a386Sopenharmony_ciclass ShaderPDXferProcessor : public GrXferProcessor { 487cb93a386Sopenharmony_cipublic: 488cb93a386Sopenharmony_ci ShaderPDXferProcessor(SkBlendMode xfermode, GrProcessorAnalysisCoverage coverage) 489cb93a386Sopenharmony_ci : INHERITED(kShaderPDXferProcessor_ClassID, /*willReadDstColor=*/true, coverage) 490cb93a386Sopenharmony_ci , fXfermode(xfermode) { 491cb93a386Sopenharmony_ci } 492cb93a386Sopenharmony_ci 493cb93a386Sopenharmony_ci const char* name() const override { return "Porter Duff Shader"; } 494cb93a386Sopenharmony_ci 495cb93a386Sopenharmony_ci SkString getShaderDfxInfo() const override; 496cb93a386Sopenharmony_ci 497cb93a386Sopenharmony_ci std::unique_ptr<ProgramImpl> makeProgramImpl() const override; 498cb93a386Sopenharmony_ci 499cb93a386Sopenharmony_ciprivate: 500cb93a386Sopenharmony_ci void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; 501cb93a386Sopenharmony_ci 502cb93a386Sopenharmony_ci bool onIsEqual(const GrXferProcessor& xpBase) const override { 503cb93a386Sopenharmony_ci const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>(); 504cb93a386Sopenharmony_ci return fXfermode == xp.fXfermode; 505cb93a386Sopenharmony_ci } 506cb93a386Sopenharmony_ci 507cb93a386Sopenharmony_ci const SkBlendMode fXfermode; 508cb93a386Sopenharmony_ci 509cb93a386Sopenharmony_ci using INHERITED = GrXferProcessor; 510cb93a386Sopenharmony_ci}; 511cb93a386Sopenharmony_ci 512cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 513cb93a386Sopenharmony_ci 514cb93a386Sopenharmony_ciSkString ShaderPDXferProcessor::getShaderDfxInfo() const 515cb93a386Sopenharmony_ci{ 516cb93a386Sopenharmony_ci SkString format; 517cb93a386Sopenharmony_ci format.printf("ShaderDfx_ShaderPDXfer_%d", fXfermode); 518cb93a386Sopenharmony_ci return format; 519cb93a386Sopenharmony_ci} 520cb93a386Sopenharmony_ci 521cb93a386Sopenharmony_civoid ShaderPDXferProcessor::onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const { 522cb93a386Sopenharmony_ci b->add32(static_cast<int>(fXfermode)); 523cb93a386Sopenharmony_ci} 524cb93a386Sopenharmony_ci 525cb93a386Sopenharmony_cistd::unique_ptr<GrXferProcessor::ProgramImpl> ShaderPDXferProcessor::makeProgramImpl() const { 526cb93a386Sopenharmony_ci class Impl : public ProgramImpl { 527cb93a386Sopenharmony_ci private: 528cb93a386Sopenharmony_ci void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder, 529cb93a386Sopenharmony_ci GrGLSLUniformHandler* uniformHandler, 530cb93a386Sopenharmony_ci const char* srcColor, 531cb93a386Sopenharmony_ci const char* srcCoverage, 532cb93a386Sopenharmony_ci const char* dstColor, 533cb93a386Sopenharmony_ci const char* outColor, 534cb93a386Sopenharmony_ci const char* outColorSecondary, 535cb93a386Sopenharmony_ci const GrXferProcessor& proc) override { 536cb93a386Sopenharmony_ci const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>(); 537cb93a386Sopenharmony_ci 538cb93a386Sopenharmony_ci GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.fXfermode); 539cb93a386Sopenharmony_ci 540cb93a386Sopenharmony_ci // Apply coverage. 541cb93a386Sopenharmony_ci DefaultCoverageModulation(fragBuilder, 542cb93a386Sopenharmony_ci srcCoverage, 543cb93a386Sopenharmony_ci dstColor, 544cb93a386Sopenharmony_ci outColor, 545cb93a386Sopenharmony_ci outColorSecondary, 546cb93a386Sopenharmony_ci xp); 547cb93a386Sopenharmony_ci } 548cb93a386Sopenharmony_ci }; 549cb93a386Sopenharmony_ci 550cb93a386Sopenharmony_ci return std::make_unique<Impl>(); 551cb93a386Sopenharmony_ci} 552cb93a386Sopenharmony_ci 553cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 554cb93a386Sopenharmony_ci 555cb93a386Sopenharmony_ciclass PDLCDXferProcessor : public GrXferProcessor { 556cb93a386Sopenharmony_cipublic: 557cb93a386Sopenharmony_ci static sk_sp<const GrXferProcessor> Make(SkBlendMode mode, 558cb93a386Sopenharmony_ci const GrProcessorAnalysisColor& inputColor); 559cb93a386Sopenharmony_ci 560cb93a386Sopenharmony_ci const char* name() const override { return "Porter Duff LCD"; } 561cb93a386Sopenharmony_ci 562cb93a386Sopenharmony_ci SkString getShaderDfxInfo() const override { return SkString("ShaderDfx_PDLCDXfer"); } 563cb93a386Sopenharmony_ci 564cb93a386Sopenharmony_ci std::unique_ptr<ProgramImpl> makeProgramImpl() const override; 565cb93a386Sopenharmony_ci 566cb93a386Sopenharmony_ciprivate: 567cb93a386Sopenharmony_ci PDLCDXferProcessor(const SkPMColor4f& blendConstant, float alpha); 568cb93a386Sopenharmony_ci 569cb93a386Sopenharmony_ci void onAddToKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {} 570cb93a386Sopenharmony_ci 571cb93a386Sopenharmony_ci void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 572cb93a386Sopenharmony_ci blendInfo->fSrcBlend = kConstC_GrBlendCoeff; 573cb93a386Sopenharmony_ci blendInfo->fDstBlend = kISC_GrBlendCoeff; 574cb93a386Sopenharmony_ci blendInfo->fBlendConstant = fBlendConstant; 575cb93a386Sopenharmony_ci } 576cb93a386Sopenharmony_ci 577cb93a386Sopenharmony_ci bool onIsEqual(const GrXferProcessor& xpBase) const override { 578cb93a386Sopenharmony_ci const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>(); 579cb93a386Sopenharmony_ci if (fBlendConstant != xp.fBlendConstant || fAlpha != xp.fAlpha) { 580cb93a386Sopenharmony_ci return false; 581cb93a386Sopenharmony_ci } 582cb93a386Sopenharmony_ci return true; 583cb93a386Sopenharmony_ci } 584cb93a386Sopenharmony_ci 585cb93a386Sopenharmony_ci SkPMColor4f fBlendConstant; 586cb93a386Sopenharmony_ci float fAlpha; 587cb93a386Sopenharmony_ci 588cb93a386Sopenharmony_ci using INHERITED = GrXferProcessor; 589cb93a386Sopenharmony_ci}; 590cb93a386Sopenharmony_ci 591cb93a386Sopenharmony_ciPDLCDXferProcessor::PDLCDXferProcessor(const SkPMColor4f& blendConstant, float alpha) 592cb93a386Sopenharmony_ci : INHERITED(kPDLCDXferProcessor_ClassID, /*willReadDstColor=*/false, 593cb93a386Sopenharmony_ci GrProcessorAnalysisCoverage::kLCD) 594cb93a386Sopenharmony_ci , fBlendConstant(blendConstant) 595cb93a386Sopenharmony_ci , fAlpha(alpha) { 596cb93a386Sopenharmony_ci} 597cb93a386Sopenharmony_ci 598cb93a386Sopenharmony_cisk_sp<const GrXferProcessor> PDLCDXferProcessor::Make(SkBlendMode mode, 599cb93a386Sopenharmony_ci const GrProcessorAnalysisColor& color) { 600cb93a386Sopenharmony_ci if (SkBlendMode::kSrcOver != mode) { 601cb93a386Sopenharmony_ci return nullptr; 602cb93a386Sopenharmony_ci } 603cb93a386Sopenharmony_ci SkPMColor4f blendConstantPM; 604cb93a386Sopenharmony_ci if (!color.isConstant(&blendConstantPM)) { 605cb93a386Sopenharmony_ci return nullptr; 606cb93a386Sopenharmony_ci } 607cb93a386Sopenharmony_ci SkColor4f blendConstantUPM = blendConstantPM.unpremul(); 608cb93a386Sopenharmony_ci float alpha = blendConstantUPM.fA; 609cb93a386Sopenharmony_ci blendConstantPM = { blendConstantUPM.fR, blendConstantUPM.fG, blendConstantUPM.fB, 1 }; 610cb93a386Sopenharmony_ci return sk_sp<GrXferProcessor>(new PDLCDXferProcessor(blendConstantPM, alpha)); 611cb93a386Sopenharmony_ci} 612cb93a386Sopenharmony_ci 613cb93a386Sopenharmony_cistd::unique_ptr<GrXferProcessor::ProgramImpl> PDLCDXferProcessor::makeProgramImpl() const { 614cb93a386Sopenharmony_ci class Impl : public ProgramImpl { 615cb93a386Sopenharmony_ci private: 616cb93a386Sopenharmony_ci void emitOutputsForBlendState(const EmitArgs& args) override { 617cb93a386Sopenharmony_ci const char* alpha; 618cb93a386Sopenharmony_ci fAlphaUniform = args.fUniformHandler->addUniform(nullptr, 619cb93a386Sopenharmony_ci kFragment_GrShaderFlag, 620cb93a386Sopenharmony_ci kHalf_GrSLType, 621cb93a386Sopenharmony_ci "alpha", 622cb93a386Sopenharmony_ci &alpha); 623cb93a386Sopenharmony_ci GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 624cb93a386Sopenharmony_ci // We want to force our primary output to be alpha * Coverage, where alpha is the alpha 625cb93a386Sopenharmony_ci // value of the src color. We know that there are no color stages (or we wouldn't have 626cb93a386Sopenharmony_ci // created this xp) and the r,g, and b channels of the op's input color are baked into 627cb93a386Sopenharmony_ci // the blend constant. 628cb93a386Sopenharmony_ci SkASSERT(args.fInputCoverage); 629cb93a386Sopenharmony_ci fragBuilder->codeAppendf("%s = %s * %s;", 630cb93a386Sopenharmony_ci args.fOutputPrimary, 631cb93a386Sopenharmony_ci alpha, args.fInputCoverage); 632cb93a386Sopenharmony_ci } 633cb93a386Sopenharmony_ci 634cb93a386Sopenharmony_ci void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override { 635cb93a386Sopenharmony_ci float alpha = xp.cast<PDLCDXferProcessor>().fAlpha; 636cb93a386Sopenharmony_ci if (fLastAlpha != alpha) { 637cb93a386Sopenharmony_ci pdm.set1f(fAlphaUniform, alpha); 638cb93a386Sopenharmony_ci fLastAlpha = alpha; 639cb93a386Sopenharmony_ci } 640cb93a386Sopenharmony_ci } 641cb93a386Sopenharmony_ci 642cb93a386Sopenharmony_ci GrGLSLUniformHandler::UniformHandle fAlphaUniform; 643cb93a386Sopenharmony_ci float fLastAlpha = SK_FloatNaN; 644cb93a386Sopenharmony_ci }; 645cb93a386Sopenharmony_ci 646cb93a386Sopenharmony_ci return std::make_unique<Impl>(); 647cb93a386Sopenharmony_ci} 648cb93a386Sopenharmony_ci 649cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 650cb93a386Sopenharmony_ci 651cb93a386Sopenharmony_ciconstexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode) 652cb93a386Sopenharmony_ci : fBlendMode(xfermode) {} 653cb93a386Sopenharmony_ci 654cb93a386Sopenharmony_ciconst GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) { 655cb93a386Sopenharmony_ci SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode); 656cb93a386Sopenharmony_ci 657cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear); 658cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc); 659cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst); 660cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver); 661cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver); 662cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn); 663cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn); 664cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut); 665cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut); 666cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop); 667cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop); 668cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor); 669cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus); 670cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate); 671cb93a386Sopenharmony_ci static constexpr const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen); 672cb93a386Sopenharmony_ci 673cb93a386Sopenharmony_ci switch (blendMode) { 674cb93a386Sopenharmony_ci case SkBlendMode::kClear: 675cb93a386Sopenharmony_ci return &gClearPDXPF; 676cb93a386Sopenharmony_ci case SkBlendMode::kSrc: 677cb93a386Sopenharmony_ci return &gSrcPDXPF; 678cb93a386Sopenharmony_ci case SkBlendMode::kDst: 679cb93a386Sopenharmony_ci return &gDstPDXPF; 680cb93a386Sopenharmony_ci case SkBlendMode::kSrcOver: 681cb93a386Sopenharmony_ci return &gSrcOverPDXPF; 682cb93a386Sopenharmony_ci case SkBlendMode::kDstOver: 683cb93a386Sopenharmony_ci return &gDstOverPDXPF; 684cb93a386Sopenharmony_ci case SkBlendMode::kSrcIn: 685cb93a386Sopenharmony_ci return &gSrcInPDXPF; 686cb93a386Sopenharmony_ci case SkBlendMode::kDstIn: 687cb93a386Sopenharmony_ci return &gDstInPDXPF; 688cb93a386Sopenharmony_ci case SkBlendMode::kSrcOut: 689cb93a386Sopenharmony_ci return &gSrcOutPDXPF; 690cb93a386Sopenharmony_ci case SkBlendMode::kDstOut: 691cb93a386Sopenharmony_ci return &gDstOutPDXPF; 692cb93a386Sopenharmony_ci case SkBlendMode::kSrcATop: 693cb93a386Sopenharmony_ci return &gSrcATopPDXPF; 694cb93a386Sopenharmony_ci case SkBlendMode::kDstATop: 695cb93a386Sopenharmony_ci return &gDstATopPDXPF; 696cb93a386Sopenharmony_ci case SkBlendMode::kXor: 697cb93a386Sopenharmony_ci return &gXorPDXPF; 698cb93a386Sopenharmony_ci case SkBlendMode::kPlus: 699cb93a386Sopenharmony_ci return &gPlusPDXPF; 700cb93a386Sopenharmony_ci case SkBlendMode::kModulate: 701cb93a386Sopenharmony_ci return &gModulatePDXPF; 702cb93a386Sopenharmony_ci case SkBlendMode::kScreen: 703cb93a386Sopenharmony_ci return &gScreenPDXPF; 704cb93a386Sopenharmony_ci default: 705cb93a386Sopenharmony_ci SK_ABORT("Unexpected blend mode."); 706cb93a386Sopenharmony_ci } 707cb93a386Sopenharmony_ci} 708cb93a386Sopenharmony_ci 709cb93a386Sopenharmony_cisk_sp<const GrXferProcessor> GrPorterDuffXPFactory::makeXferProcessor( 710cb93a386Sopenharmony_ci const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage, 711cb93a386Sopenharmony_ci const GrCaps& caps, GrClampType clampType) const { 712cb93a386Sopenharmony_ci bool isLCD = coverage == GrProcessorAnalysisCoverage::kLCD; 713cb93a386Sopenharmony_ci // See comment in MakeSrcOverXferProcessor about color.isOpaque here 714cb93a386Sopenharmony_ci if (isLCD && 715cb93a386Sopenharmony_ci SkBlendMode::kSrcOver == fBlendMode && color.isConstant() && /*color.isOpaque() &&*/ 716cb93a386Sopenharmony_ci !caps.shaderCaps()->dualSourceBlendingSupport() && 717cb93a386Sopenharmony_ci !caps.shaderCaps()->dstReadInShaderSupport()) { 718cb93a386Sopenharmony_ci // If we don't have dual source blending or in shader dst reads, we fall back to this 719cb93a386Sopenharmony_ci // trick for rendering SrcOver LCD text instead of doing a dst copy. 720cb93a386Sopenharmony_ci return PDLCDXferProcessor::Make(fBlendMode, color); 721cb93a386Sopenharmony_ci } 722cb93a386Sopenharmony_ci BlendFormula blendFormula = [&](){ 723cb93a386Sopenharmony_ci if (isLCD) { 724cb93a386Sopenharmony_ci return get_lcd_blend_formula(fBlendMode); 725cb93a386Sopenharmony_ci } 726cb93a386Sopenharmony_ci if (fBlendMode == SkBlendMode::kSrcOver && color.isOpaque() && 727cb93a386Sopenharmony_ci coverage == GrProcessorAnalysisCoverage::kNone && 728cb93a386Sopenharmony_ci caps.shouldCollapseSrcOverToSrcWhenAble()) 729cb93a386Sopenharmony_ci { 730cb93a386Sopenharmony_ci return get_blend_formula(true, false, SkBlendMode::kSrc); 731cb93a386Sopenharmony_ci } 732cb93a386Sopenharmony_ci return get_blend_formula(color.isOpaque(), GrProcessorAnalysisCoverage::kNone != coverage, 733cb93a386Sopenharmony_ci fBlendMode); 734cb93a386Sopenharmony_ci }(); 735cb93a386Sopenharmony_ci 736cb93a386Sopenharmony_ci // Skia always saturates after the kPlus blend mode, so it requires shader-based blending when 737cb93a386Sopenharmony_ci // pixels aren't guaranteed to automatically be normalized (i.e. any floating point config). 738cb93a386Sopenharmony_ci if ((blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) || 739cb93a386Sopenharmony_ci (isLCD && (SkBlendMode::kSrcOver != fBlendMode /*|| !color.isOpaque()*/)) || 740cb93a386Sopenharmony_ci (GrClampType::kAuto != clampType && SkBlendMode::kPlus == fBlendMode)) { 741cb93a386Sopenharmony_ci return sk_sp<const GrXferProcessor>(new ShaderPDXferProcessor(fBlendMode, coverage)); 742cb93a386Sopenharmony_ci } 743cb93a386Sopenharmony_ci return sk_sp<const GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage)); 744cb93a386Sopenharmony_ci} 745cb93a386Sopenharmony_ci 746cb93a386Sopenharmony_cistatic inline GrXPFactory::AnalysisProperties analysis_properties( 747cb93a386Sopenharmony_ci const GrProcessorAnalysisColor& color, const GrProcessorAnalysisCoverage& coverage, 748cb93a386Sopenharmony_ci const GrCaps& caps, GrClampType clampType, SkBlendMode mode) { 749cb93a386Sopenharmony_ci using AnalysisProperties = GrXPFactory::AnalysisProperties; 750cb93a386Sopenharmony_ci AnalysisProperties props = AnalysisProperties::kNone; 751cb93a386Sopenharmony_ci bool hasCoverage = GrProcessorAnalysisCoverage::kNone != coverage; 752cb93a386Sopenharmony_ci bool isLCD = GrProcessorAnalysisCoverage::kLCD == coverage; 753cb93a386Sopenharmony_ci BlendFormula formula = [&](){ 754cb93a386Sopenharmony_ci if (isLCD) { 755cb93a386Sopenharmony_ci return gLCDBlendTable[(int)mode]; 756cb93a386Sopenharmony_ci } 757cb93a386Sopenharmony_ci return get_blend_formula(color.isOpaque(), hasCoverage, mode); 758cb93a386Sopenharmony_ci }(); 759cb93a386Sopenharmony_ci 760cb93a386Sopenharmony_ci if (formula.canTweakAlphaForCoverage() && !isLCD) { 761cb93a386Sopenharmony_ci props |= AnalysisProperties::kCompatibleWithCoverageAsAlpha; 762cb93a386Sopenharmony_ci } 763cb93a386Sopenharmony_ci 764cb93a386Sopenharmony_ci if (isLCD) { 765cb93a386Sopenharmony_ci // See comment in MakeSrcOverXferProcessor about color.isOpaque here 766cb93a386Sopenharmony_ci if (SkBlendMode::kSrcOver == mode && color.isConstant() && /*color.isOpaque() &&*/ 767cb93a386Sopenharmony_ci !caps.shaderCaps()->dualSourceBlendingSupport() && 768cb93a386Sopenharmony_ci !caps.shaderCaps()->dstReadInShaderSupport()) { 769cb93a386Sopenharmony_ci props |= AnalysisProperties::kIgnoresInputColor; 770cb93a386Sopenharmony_ci } else { 771cb93a386Sopenharmony_ci // For LCD blending, if the color is not opaque we must read the dst in shader even if 772cb93a386Sopenharmony_ci // we have dual source blending. The opaqueness check must be done after blending so for 773cb93a386Sopenharmony_ci // simplicity we only allow src-over to not take the dst read path (though src, src-in, 774cb93a386Sopenharmony_ci // and DstATop would also work). We also fall into the dst read case for src-over if we 775cb93a386Sopenharmony_ci // do not have dual source blending. 776cb93a386Sopenharmony_ci if (SkBlendMode::kSrcOver != mode || 777cb93a386Sopenharmony_ci /*!color.isOpaque() ||*/ // See comment in MakeSrcOverXferProcessor about isOpaque. 778cb93a386Sopenharmony_ci (formula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) { 779cb93a386Sopenharmony_ci props |= AnalysisProperties::kReadsDstInShader; 780cb93a386Sopenharmony_ci } 781cb93a386Sopenharmony_ci } 782cb93a386Sopenharmony_ci } else { 783cb93a386Sopenharmony_ci // With dual-source blending we never need the destination color in the shader. 784cb93a386Sopenharmony_ci if (!caps.shaderCaps()->dualSourceBlendingSupport()) { 785cb93a386Sopenharmony_ci if (formula.hasSecondaryOutput()) { 786cb93a386Sopenharmony_ci props |= AnalysisProperties::kReadsDstInShader; 787cb93a386Sopenharmony_ci } 788cb93a386Sopenharmony_ci } 789cb93a386Sopenharmony_ci } 790cb93a386Sopenharmony_ci 791cb93a386Sopenharmony_ci if (GrClampType::kAuto != clampType && SkBlendMode::kPlus == mode) { 792cb93a386Sopenharmony_ci props |= AnalysisProperties::kReadsDstInShader; 793cb93a386Sopenharmony_ci } 794cb93a386Sopenharmony_ci 795cb93a386Sopenharmony_ci if (!formula.modifiesDst() || !formula.usesInputColor()) { 796cb93a386Sopenharmony_ci props |= AnalysisProperties::kIgnoresInputColor; 797cb93a386Sopenharmony_ci } 798cb93a386Sopenharmony_ci if (formula.unaffectedByDst() || (formula.unaffectedByDstIfOpaque() && color.isOpaque() && 799cb93a386Sopenharmony_ci !hasCoverage)) { 800cb93a386Sopenharmony_ci props |= AnalysisProperties::kUnaffectedByDstValue; 801cb93a386Sopenharmony_ci } 802cb93a386Sopenharmony_ci return props; 803cb93a386Sopenharmony_ci} 804cb93a386Sopenharmony_ci 805cb93a386Sopenharmony_ciGrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties( 806cb93a386Sopenharmony_ci const GrProcessorAnalysisColor& color, 807cb93a386Sopenharmony_ci const GrProcessorAnalysisCoverage& coverage, 808cb93a386Sopenharmony_ci const GrCaps& caps, 809cb93a386Sopenharmony_ci GrClampType clampType) const { 810cb93a386Sopenharmony_ci return analysis_properties(color, coverage, caps, clampType, fBlendMode); 811cb93a386Sopenharmony_ci} 812cb93a386Sopenharmony_ci 813cb93a386Sopenharmony_ciGR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); 814cb93a386Sopenharmony_ci 815cb93a386Sopenharmony_ci#if GR_TEST_UTILS 816cb93a386Sopenharmony_ciconst GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) { 817cb93a386Sopenharmony_ci SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode)); 818cb93a386Sopenharmony_ci return GrPorterDuffXPFactory::Get(mode); 819cb93a386Sopenharmony_ci} 820cb93a386Sopenharmony_ci#endif 821cb93a386Sopenharmony_ci 822cb93a386Sopenharmony_civoid GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, 823cb93a386Sopenharmony_ci int* outPrimary, 824cb93a386Sopenharmony_ci int* outSecondary) { 825cb93a386Sopenharmony_ci if (!!strcmp(xp->name(), "Porter Duff")) { 826cb93a386Sopenharmony_ci *outPrimary = *outSecondary = -1; 827cb93a386Sopenharmony_ci return; 828cb93a386Sopenharmony_ci } 829cb93a386Sopenharmony_ci BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula(); 830cb93a386Sopenharmony_ci *outPrimary = blendFormula.primaryOutput(); 831cb93a386Sopenharmony_ci *outSecondary = blendFormula.secondaryOutput(); 832cb93a386Sopenharmony_ci} 833cb93a386Sopenharmony_ci 834cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////////////// 835cb93a386Sopenharmony_ci// SrcOver Global functions 836cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////////////// 837cb93a386Sopenharmony_ciconst GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() { 838cb93a386Sopenharmony_ci static BlendFormula gSrcOverBlendFormula = 839cb93a386Sopenharmony_ci MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff); 840cb93a386Sopenharmony_ci static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula, 841cb93a386Sopenharmony_ci GrProcessorAnalysisCoverage::kSingleChannel); 842cb93a386Sopenharmony_ci return gSrcOverXP; 843cb93a386Sopenharmony_ci} 844cb93a386Sopenharmony_ci 845cb93a386Sopenharmony_cisk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeSrcOverXferProcessor( 846cb93a386Sopenharmony_ci const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage, 847cb93a386Sopenharmony_ci const GrCaps& caps) { 848cb93a386Sopenharmony_ci // We want to not make an xfer processor if possible. Thus for the simple case where we are not 849cb93a386Sopenharmony_ci // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from 850cb93a386Sopenharmony_ci // the general case where we convert a src-over blend that has solid coverage and an opaque 851cb93a386Sopenharmony_ci // color to src-mode, which allows disabling of blending. 852cb93a386Sopenharmony_ci if (coverage != GrProcessorAnalysisCoverage::kLCD) { 853cb93a386Sopenharmony_ci if (color.isOpaque() && coverage == GrProcessorAnalysisCoverage::kNone && 854cb93a386Sopenharmony_ci caps.shouldCollapseSrcOverToSrcWhenAble()) { 855cb93a386Sopenharmony_ci BlendFormula blendFormula = get_blend_formula(true, false, SkBlendMode::kSrc); 856cb93a386Sopenharmony_ci return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage)); 857cb93a386Sopenharmony_ci } 858cb93a386Sopenharmony_ci // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP". 859cb93a386Sopenharmony_ci // We don't simply return the address of that XP here because our caller would have to unref 860cb93a386Sopenharmony_ci // it and since it is a global object and GrProgramElement's ref-cnting system is not thread 861cb93a386Sopenharmony_ci // safe. 862cb93a386Sopenharmony_ci return nullptr; 863cb93a386Sopenharmony_ci } 864cb93a386Sopenharmony_ci 865cb93a386Sopenharmony_ci // Currently up the stack Skia is requiring that the dst is opaque or that the client has said 866cb93a386Sopenharmony_ci // the opaqueness doesn't matter. Thus for src-over we don't need to worry about the src color 867cb93a386Sopenharmony_ci // being opaque or not. This allows us to use faster code paths as well as avoid various bugs 868cb93a386Sopenharmony_ci // that occur with dst reads in the shader blending. For now we disable the check for 869cb93a386Sopenharmony_ci // opaqueness, but in the future we should pass down the knowledge about dst opaqueness and make 870cb93a386Sopenharmony_ci // the correct decision here. 871cb93a386Sopenharmony_ci // 872cb93a386Sopenharmony_ci // This also fixes a chrome bug on macs where we are getting random fuzziness when doing 873cb93a386Sopenharmony_ci // blending in the shader for non opaque sources. 874cb93a386Sopenharmony_ci if (color.isConstant() && /*color.isOpaque() &&*/ 875cb93a386Sopenharmony_ci !caps.shaderCaps()->dualSourceBlendingSupport() && 876cb93a386Sopenharmony_ci !caps.shaderCaps()->dstReadInShaderSupport()) { 877cb93a386Sopenharmony_ci // If we don't have dual source blending or in shader dst reads, we fall 878cb93a386Sopenharmony_ci // back to this trick for rendering SrcOver LCD text instead of doing a 879cb93a386Sopenharmony_ci // dst copy. 880cb93a386Sopenharmony_ci return PDLCDXferProcessor::Make(SkBlendMode::kSrcOver, color); 881cb93a386Sopenharmony_ci } 882cb93a386Sopenharmony_ci 883cb93a386Sopenharmony_ci BlendFormula blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver); 884cb93a386Sopenharmony_ci // See comment above regarding why the opaque check is commented out here. 885cb93a386Sopenharmony_ci if (/*!color.isOpaque() ||*/ 886cb93a386Sopenharmony_ci (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) { 887cb93a386Sopenharmony_ci return sk_sp<GrXferProcessor>(new ShaderPDXferProcessor(SkBlendMode::kSrcOver, coverage)); 888cb93a386Sopenharmony_ci } 889cb93a386Sopenharmony_ci return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage)); 890cb93a386Sopenharmony_ci} 891cb93a386Sopenharmony_ci 892cb93a386Sopenharmony_cisk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeNoCoverageXP(SkBlendMode blendmode) { 893cb93a386Sopenharmony_ci BlendFormula formula = get_blend_formula(false, false, blendmode); 894cb93a386Sopenharmony_ci return sk_make_sp<PorterDuffXferProcessor>(formula, GrProcessorAnalysisCoverage::kNone); 895cb93a386Sopenharmony_ci} 896cb93a386Sopenharmony_ci 897cb93a386Sopenharmony_ciGrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties( 898cb93a386Sopenharmony_ci const GrProcessorAnalysisColor& color, 899cb93a386Sopenharmony_ci const GrProcessorAnalysisCoverage& coverage, 900cb93a386Sopenharmony_ci const GrCaps& caps, 901cb93a386Sopenharmony_ci GrClampType clampType) { 902cb93a386Sopenharmony_ci return analysis_properties(color, coverage, caps, clampType, SkBlendMode::kSrcOver); 903cb93a386Sopenharmony_ci} 904