1378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel/* 2378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel * Copyright 2014 Google Inc. 3378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel * 4378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel * Use of this source code is governed by a BSD-style license that can be 5378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel * found in the LICENSE file. 6378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel */ 7378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel 8ced90108b763b1eb3bd7f78b5614d4643b577a24egdaniel#include "effects/GrPorterDuffXferProcessor.h" 9378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel 109513143efa734bef0c1a0c7f945022572dbc8518egdaniel#include "GrBlend.h" 11eb1cb5c5b50febad115d859faca91d2d6af3fff2bsalomon#include "GrCaps.h" 12de4166a3b45d859512e27e3257841f064d67549cethannicholas#include "GrPipeline.h" 13378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "GrProcessor.h" 14a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon#include "GrProcessorAnalysis.h" 15378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "GrTypes.h" 16378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel#include "GrXferProcessor.h" 1764c4728c70001ed074fecf5c4e083781987b12e9egdaniel#include "glsl/GrGLSLBlend.h" 182d721d33aad192cc8a7a1321504b39bdca2a57ceegdaniel#include "glsl/GrGLSLFragmentShaderBuilder.h" 19018fb62d12d1febf121fe265da5b6117b86a6541egdaniel#include "glsl/GrGLSLProgramDataManager.h" 207ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "glsl/GrGLSLUniformHandler.h" 21fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdaniel#include "glsl/GrGLSLXferProcessor.h" 22378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel 236fd158ea47472c4d038e48980a95e36623f840c9cdalton/** 246fd158ea47472c4d038e48980a95e36623f840c9cdalton * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage. 256fd158ea47472c4d038e48980a95e36623f840c9cdalton */ 267b29749c13deab4588cbe0414a93191326800712Brian Salomonclass BlendFormula { 276fd158ea47472c4d038e48980a95e36623f840c9cdaltonpublic: 286fd158ea47472c4d038e48980a95e36623f840c9cdalton /** 296fd158ea47472c4d038e48980a95e36623f840c9cdalton * Values the shader can write to primary and secondary outputs. These must all be modulated by 306fd158ea47472c4d038e48980a95e36623f840c9cdalton * coverage to support mixed samples. The XP will ignore the multiplies when not using coverage. 319513143efa734bef0c1a0c7f945022572dbc8518egdaniel */ 326fd158ea47472c4d038e48980a95e36623f840c9cdalton enum OutputType { 336fd158ea47472c4d038e48980a95e36623f840c9cdalton kNone_OutputType, //<! 0 346fd158ea47472c4d038e48980a95e36623f840c9cdalton kCoverage_OutputType, //<! inputCoverage 356fd158ea47472c4d038e48980a95e36623f840c9cdalton kModulate_OutputType, //<! inputColor * inputCoverage 36723b0501e22373bb3e6c306daaceae02cda8a124egdaniel kSAModulate_OutputType, //<! inputColor.a * inputCoverage 376fd158ea47472c4d038e48980a95e36623f840c9cdalton kISAModulate_OutputType, //<! (1 - inputColor.a) * inputCoverage 386fd158ea47472c4d038e48980a95e36623f840c9cdalton kISCModulate_OutputType, //<! (1 - inputColor) * inputCoverage 396fd158ea47472c4d038e48980a95e36623f840c9cdalton 406fd158ea47472c4d038e48980a95e36623f840c9cdalton kLast_OutputType = kISCModulate_OutputType 416fd158ea47472c4d038e48980a95e36623f840c9cdalton }; 429513143efa734bef0c1a0c7f945022572dbc8518egdaniel 437b29749c13deab4588cbe0414a93191326800712Brian Salomon BlendFormula() = default; 446fd158ea47472c4d038e48980a95e36623f840c9cdalton 457b29749c13deab4588cbe0414a93191326800712Brian Salomon constexpr BlendFormula(OutputType primaryOut, OutputType secondaryOut, GrBlendEquation equation, 467b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) 477b29749c13deab4588cbe0414a93191326800712Brian Salomon : fPrimaryOutputType(primaryOut) 487b29749c13deab4588cbe0414a93191326800712Brian Salomon , fSecondaryOutputType(secondaryOut) 497b29749c13deab4588cbe0414a93191326800712Brian Salomon , fBlendEquation(equation) 507b29749c13deab4588cbe0414a93191326800712Brian Salomon , fSrcCoeff(srcCoeff) 517b29749c13deab4588cbe0414a93191326800712Brian Salomon , fDstCoeff(dstCoeff) 527b29749c13deab4588cbe0414a93191326800712Brian Salomon , fProps(GetProperties(primaryOut, secondaryOut, equation, srcCoeff, dstCoeff)) {} 5341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 547b29749c13deab4588cbe0414a93191326800712Brian Salomon BlendFormula& operator=(const BlendFormula& other) { 557b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(other.validatePreoptimized()); 566fd158ea47472c4d038e48980a95e36623f840c9cdalton fData = other.fData; 576fd158ea47472c4d038e48980a95e36623f840c9cdalton return *this; 586fd158ea47472c4d038e48980a95e36623f840c9cdalton } 5941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 607b29749c13deab4588cbe0414a93191326800712Brian Salomon bool operator==(const BlendFormula& other) const { 617b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 627b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(other.validatePreoptimized()); 636fd158ea47472c4d038e48980a95e36623f840c9cdalton return fData == other.fData; 646fd158ea47472c4d038e48980a95e36623f840c9cdalton } 6541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 667b29749c13deab4588cbe0414a93191326800712Brian Salomon bool hasSecondaryOutput() const { 677b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 687b29749c13deab4588cbe0414a93191326800712Brian Salomon return kNone_OutputType != fSecondaryOutputType; 697b29749c13deab4588cbe0414a93191326800712Brian Salomon } 707b29749c13deab4588cbe0414a93191326800712Brian Salomon bool modifiesDst() const { 717b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 727b29749c13deab4588cbe0414a93191326800712Brian Salomon return SkToBool(fProps & kModifiesDst_Property); 737b29749c13deab4588cbe0414a93191326800712Brian Salomon } 747b29749c13deab4588cbe0414a93191326800712Brian Salomon bool usesDstColor() const { 757b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 767b29749c13deab4588cbe0414a93191326800712Brian Salomon return SkToBool(fProps & kUsesDstColor_Property); 777b29749c13deab4588cbe0414a93191326800712Brian Salomon } 787b29749c13deab4588cbe0414a93191326800712Brian Salomon bool usesInputColor() const { 797b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 807b29749c13deab4588cbe0414a93191326800712Brian Salomon return SkToBool(fProps & kUsesInputColor_Property); 817b29749c13deab4588cbe0414a93191326800712Brian Salomon } 826fd158ea47472c4d038e48980a95e36623f840c9cdalton bool canTweakAlphaForCoverage() const { 837b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 846fd158ea47472c4d038e48980a95e36623f840c9cdalton return SkToBool(fProps & kCanTweakAlphaForCoverage_Property); 856fd158ea47472c4d038e48980a95e36623f840c9cdalton } 8641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 877b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendEquation equation() const { 887b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 897b29749c13deab4588cbe0414a93191326800712Brian Salomon return fBlendEquation; 907b29749c13deab4588cbe0414a93191326800712Brian Salomon } 917b29749c13deab4588cbe0414a93191326800712Brian Salomon 927b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendCoeff srcCoeff() const { 937b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 947b29749c13deab4588cbe0414a93191326800712Brian Salomon return fSrcCoeff; 957b29749c13deab4588cbe0414a93191326800712Brian Salomon } 967b29749c13deab4588cbe0414a93191326800712Brian Salomon 977b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendCoeff dstCoeff() const { 987b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 997b29749c13deab4588cbe0414a93191326800712Brian Salomon return fDstCoeff; 1007b29749c13deab4588cbe0414a93191326800712Brian Salomon } 1017b29749c13deab4588cbe0414a93191326800712Brian Salomon 1027b29749c13deab4588cbe0414a93191326800712Brian Salomon OutputType primaryOutput() const { 1037b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 1047b29749c13deab4588cbe0414a93191326800712Brian Salomon return fPrimaryOutputType; 1057b29749c13deab4588cbe0414a93191326800712Brian Salomon } 1067b29749c13deab4588cbe0414a93191326800712Brian Salomon 1077b29749c13deab4588cbe0414a93191326800712Brian Salomon OutputType secondaryOutput() const { 1087b29749c13deab4588cbe0414a93191326800712Brian Salomon SkDEBUGCODE(this->validatePreoptimized()); 1097b29749c13deab4588cbe0414a93191326800712Brian Salomon return fSecondaryOutputType; 1107b29749c13deab4588cbe0414a93191326800712Brian Salomon } 1117b29749c13deab4588cbe0414a93191326800712Brian Salomon 1127b29749c13deab4588cbe0414a93191326800712Brian Salomonprivate: 1137b29749c13deab4588cbe0414a93191326800712Brian Salomon enum Properties { 1147b29749c13deab4588cbe0414a93191326800712Brian Salomon kModifiesDst_Property = 1, 1157b29749c13deab4588cbe0414a93191326800712Brian Salomon kUsesDstColor_Property = 1 << 1, 1167b29749c13deab4588cbe0414a93191326800712Brian Salomon kUsesInputColor_Property = 1 << 2, 1177b29749c13deab4588cbe0414a93191326800712Brian Salomon kCanTweakAlphaForCoverage_Property = 1 << 3, 1187b29749c13deab4588cbe0414a93191326800712Brian Salomon 1197b29749c13deab4588cbe0414a93191326800712Brian Salomon kLast_Property = kCanTweakAlphaForCoverage_Property 1207b29749c13deab4588cbe0414a93191326800712Brian Salomon }; 1217b29749c13deab4588cbe0414a93191326800712Brian Salomon GR_DECL_BITFIELD_OPS_FRIENDS(Properties) 1227b29749c13deab4588cbe0414a93191326800712Brian Salomon 1237b29749c13deab4588cbe0414a93191326800712Brian Salomon#ifdef SK_DEBUG 1247b29749c13deab4588cbe0414a93191326800712Brian Salomon void validatePreoptimized() const { 1257b29749c13deab4588cbe0414a93191326800712Brian Salomon // The provided formula should already be optimized before a BlendFormula is constructed. 1267b29749c13deab4588cbe0414a93191326800712Brian Salomon // Preferably these asserts would be done statically in the constexpr constructor, but this 1277b29749c13deab4588cbe0414a93191326800712Brian Salomon // is not allowed in C++11. 1287b29749c13deab4588cbe0414a93191326800712Brian Salomon SkASSERT((kNone_OutputType == fPrimaryOutputType) == 1297b29749c13deab4588cbe0414a93191326800712Brian Salomon !GrBlendCoeffsUseSrcColor(fSrcCoeff, fDstCoeff)); 1307b29749c13deab4588cbe0414a93191326800712Brian Salomon SkASSERT(!GrBlendCoeffRefsSrc2(fSrcCoeff)); 1317b29749c13deab4588cbe0414a93191326800712Brian Salomon SkASSERT((kNone_OutputType == fSecondaryOutputType) == !GrBlendCoeffRefsSrc2(fDstCoeff)); 1327b29749c13deab4588cbe0414a93191326800712Brian Salomon SkASSERT(fPrimaryOutputType != fSecondaryOutputType || 1337b29749c13deab4588cbe0414a93191326800712Brian Salomon kNone_OutputType == fPrimaryOutputType); 1347b29749c13deab4588cbe0414a93191326800712Brian Salomon SkASSERT(kNone_OutputType != fPrimaryOutputType || 1357b29749c13deab4588cbe0414a93191326800712Brian Salomon kNone_OutputType == fSecondaryOutputType); 1367b29749c13deab4588cbe0414a93191326800712Brian Salomon } 1377b29749c13deab4588cbe0414a93191326800712Brian Salomon#endif 1387b29749c13deab4588cbe0414a93191326800712Brian Salomon 1396fd158ea47472c4d038e48980a95e36623f840c9cdalton /** 1407b29749c13deab4588cbe0414a93191326800712Brian Salomon * Deduce the properties of a BlendFormula. 1416fd158ea47472c4d038e48980a95e36623f840c9cdalton */ 1427b29749c13deab4588cbe0414a93191326800712Brian Salomon static constexpr Properties GetProperties(OutputType PrimaryOut, OutputType SecondaryOut, 1437b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendEquation BlendEquation, GrBlendCoeff SrcCoeff, 1447b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendCoeff DstCoeff); 145c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman 1466fd158ea47472c4d038e48980a95e36623f840c9cdalton union { 1476fd158ea47472c4d038e48980a95e36623f840c9cdalton struct { 1486fd158ea47472c4d038e48980a95e36623f840c9cdalton // We allot the enums one more bit than they require because MSVC seems to sign-extend 1496fd158ea47472c4d038e48980a95e36623f840c9cdalton // them when the top bit is set. (This is in violation of the C++03 standard 9.6/4) 1506fd158ea47472c4d038e48980a95e36623f840c9cdalton OutputType fPrimaryOutputType : 4; 1516fd158ea47472c4d038e48980a95e36623f840c9cdalton OutputType fSecondaryOutputType : 4; 1526fd158ea47472c4d038e48980a95e36623f840c9cdalton GrBlendEquation fBlendEquation : 6; 1536fd158ea47472c4d038e48980a95e36623f840c9cdalton GrBlendCoeff fSrcCoeff : 6; 1546fd158ea47472c4d038e48980a95e36623f840c9cdalton GrBlendCoeff fDstCoeff : 6; 1556fd158ea47472c4d038e48980a95e36623f840c9cdalton Properties fProps : 32 - (4 + 4 + 6 + 6 + 6); 1566fd158ea47472c4d038e48980a95e36623f840c9cdalton }; 1576fd158ea47472c4d038e48980a95e36623f840c9cdalton uint32_t fData; 158c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman }; 15941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 1606fd158ea47472c4d038e48980a95e36623f840c9cdalton GR_STATIC_ASSERT(kLast_OutputType < (1 << 3)); 1616fd158ea47472c4d038e48980a95e36623f840c9cdalton GR_STATIC_ASSERT(kLast_GrBlendEquation < (1 << 5)); 1626fd158ea47472c4d038e48980a95e36623f840c9cdalton GR_STATIC_ASSERT(kLast_GrBlendCoeff < (1 << 5)); 1636fd158ea47472c4d038e48980a95e36623f840c9cdalton GR_STATIC_ASSERT(kLast_Property < (1 << 6)); 1646fd158ea47472c4d038e48980a95e36623f840c9cdalton}; 1656fd158ea47472c4d038e48980a95e36623f840c9cdalton 1666fd158ea47472c4d038e48980a95e36623f840c9cdaltonGR_STATIC_ASSERT(4 == sizeof(BlendFormula)); 1676fd158ea47472c4d038e48980a95e36623f840c9cdalton 1686fd158ea47472c4d038e48980a95e36623f840c9cdaltonGR_MAKE_BITFIELD_OPS(BlendFormula::Properties); 1696fd158ea47472c4d038e48980a95e36623f840c9cdalton 1707b29749c13deab4588cbe0414a93191326800712Brian Salomonconstexpr BlendFormula::Properties BlendFormula::GetProperties(OutputType PrimaryOut, 1717b29749c13deab4588cbe0414a93191326800712Brian Salomon OutputType SecondaryOut, 1727b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendEquation BlendEquation, 1737b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendCoeff SrcCoeff, 1747b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendCoeff DstCoeff) { 1757b29749c13deab4588cbe0414a93191326800712Brian Salomon return static_cast<Properties>( 1767b29749c13deab4588cbe0414a93191326800712Brian Salomon (GrBlendModifiesDst(BlendEquation, SrcCoeff, DstCoeff) ? kModifiesDst_Property : 0) | 1777b29749c13deab4588cbe0414a93191326800712Brian Salomon (GrBlendCoeffsUseDstColor(SrcCoeff, DstCoeff) ? kUsesDstColor_Property : 0) | 1787b29749c13deab4588cbe0414a93191326800712Brian Salomon ((PrimaryOut >= kModulate_OutputType && GrBlendCoeffsUseSrcColor(SrcCoeff, DstCoeff)) || 1797b29749c13deab4588cbe0414a93191326800712Brian Salomon (SecondaryOut >= kModulate_OutputType && 1807b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendCoeffRefsSrc2(DstCoeff)) 1817b29749c13deab4588cbe0414a93191326800712Brian Salomon ? kUsesInputColor_Property 1827b29749c13deab4588cbe0414a93191326800712Brian Salomon : 0) | // We assert later that SrcCoeff doesn't ref src2. 1837b29749c13deab4588cbe0414a93191326800712Brian Salomon ((kModulate_OutputType == PrimaryOut || kNone_OutputType == PrimaryOut) && 1847b29749c13deab4588cbe0414a93191326800712Brian Salomon kNone_OutputType == SecondaryOut && 1857b29749c13deab4588cbe0414a93191326800712Brian Salomon GrBlendAllowsCoverageAsAlpha(BlendEquation, SrcCoeff, DstCoeff) 1867b29749c13deab4588cbe0414a93191326800712Brian Salomon ? kCanTweakAlphaForCoverage_Property 1877b29749c13deab4588cbe0414a93191326800712Brian Salomon : 0)); 1887b29749c13deab4588cbe0414a93191326800712Brian Salomon} 1896fd158ea47472c4d038e48980a95e36623f840c9cdalton 1906fd158ea47472c4d038e48980a95e36623f840c9cdalton/** 1916fd158ea47472c4d038e48980a95e36623f840c9cdalton * When there is no coverage, or the blend mode can tweak alpha for coverage, we use the standard 1926fd158ea47472c4d038e48980a95e36623f840c9cdalton * Porter Duff formula. 1936fd158ea47472c4d038e48980a95e36623f840c9cdalton */ 1947b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic constexpr BlendFormula MakeCoeffFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 1957b29749c13deab4588cbe0414a93191326800712Brian Salomon // When the coeffs are (Zero, Zero) or (Zero, One) we set the primary output to none. 1967b29749c13deab4588cbe0414a93191326800712Brian Salomon return (kZero_GrBlendCoeff == srcCoeff && 1977b29749c13deab4588cbe0414a93191326800712Brian Salomon (kZero_GrBlendCoeff == dstCoeff || kOne_GrBlendCoeff == dstCoeff)) 1987b29749c13deab4588cbe0414a93191326800712Brian Salomon ? BlendFormula(BlendFormula::kNone_OutputType, BlendFormula::kNone_OutputType, 1997b29749c13deab4588cbe0414a93191326800712Brian Salomon kAdd_GrBlendEquation, kZero_GrBlendCoeff, dstCoeff) 2007b29749c13deab4588cbe0414a93191326800712Brian Salomon : BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kNone_OutputType, 2017b29749c13deab4588cbe0414a93191326800712Brian Salomon kAdd_GrBlendEquation, srcCoeff, dstCoeff); 2027b29749c13deab4588cbe0414a93191326800712Brian Salomon} 2036fd158ea47472c4d038e48980a95e36623f840c9cdalton 2046fd158ea47472c4d038e48980a95e36623f840c9cdalton/** 2057b29749c13deab4588cbe0414a93191326800712Brian Salomon * Basic coeff formula similar to MakeCoeffFormula but we will make the src f*Sa. This is used in 206723b0501e22373bb3e6c306daaceae02cda8a124egdaniel * LCD dst-out. 207723b0501e22373bb3e6c306daaceae02cda8a124egdaniel */ 2087b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic constexpr BlendFormula MakeSAModulateFormula(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { 2097b29749c13deab4588cbe0414a93191326800712Brian Salomon return BlendFormula(BlendFormula::kSAModulate_OutputType, BlendFormula::kNone_OutputType, 2107b29749c13deab4588cbe0414a93191326800712Brian Salomon kAdd_GrBlendEquation, srcCoeff, dstCoeff); 2117b29749c13deab4588cbe0414a93191326800712Brian Salomon} 212c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman 2136fd158ea47472c4d038e48980a95e36623f840c9cdalton/** 2146fd158ea47472c4d038e48980a95e36623f840c9cdalton * When there is coverage, the equation with f=coverage is: 2156fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2166fd158ea47472c4d038e48980a95e36623f840c9cdalton * D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D 2176fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2186fd158ea47472c4d038e48980a95e36623f840c9cdalton * This can be rewritten as: 2196fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2206fd158ea47472c4d038e48980a95e36623f840c9cdalton * D' = f * S * srcCoeff + D * (1 - [f * (1 - dstCoeff)]) 2216fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2226fd158ea47472c4d038e48980a95e36623f840c9cdalton * To implement this formula, we output [f * (1 - dstCoeff)] for the secondary color and replace the 2236fd158ea47472c4d038e48980a95e36623f840c9cdalton * HW dst coeff with IS2C. 2246fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2256fd158ea47472c4d038e48980a95e36623f840c9cdalton * Xfer modes: dst-atop (Sa!=1) 2266fd158ea47472c4d038e48980a95e36623f840c9cdalton */ 2277b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic constexpr BlendFormula MakeCoverageFormula( 2287b29749c13deab4588cbe0414a93191326800712Brian Salomon BlendFormula::OutputType oneMinusDstCoeffModulateOutput, GrBlendCoeff srcCoeff) { 2297b29749c13deab4588cbe0414a93191326800712Brian Salomon return BlendFormula(BlendFormula::kModulate_OutputType, oneMinusDstCoeffModulateOutput, 2307b29749c13deab4588cbe0414a93191326800712Brian Salomon kAdd_GrBlendEquation, srcCoeff, kIS2C_GrBlendCoeff); 2317b29749c13deab4588cbe0414a93191326800712Brian Salomon} 2326fd158ea47472c4d038e48980a95e36623f840c9cdalton 2336fd158ea47472c4d038e48980a95e36623f840c9cdalton/** 2346fd158ea47472c4d038e48980a95e36623f840c9cdalton * When there is coverage and the src coeff is Zero, the equation with f=coverage becomes: 2356fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2366fd158ea47472c4d038e48980a95e36623f840c9cdalton * D' = f * D * dstCoeff + (1-f) * D 2376fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2386fd158ea47472c4d038e48980a95e36623f840c9cdalton * This can be rewritten as: 2396fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2406fd158ea47472c4d038e48980a95e36623f840c9cdalton * D' = D - D * [f * (1 - dstCoeff)] 2416fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2426fd158ea47472c4d038e48980a95e36623f840c9cdalton * To implement this formula, we output [f * (1 - dstCoeff)] for the primary color and use a reverse 2436fd158ea47472c4d038e48980a95e36623f840c9cdalton * subtract HW blend equation with coeffs of (DC, One). 2446fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2456fd158ea47472c4d038e48980a95e36623f840c9cdalton * Xfer modes: clear, dst-out (Sa=1), dst-in (Sa!=1), modulate (Sc!=1) 2466fd158ea47472c4d038e48980a95e36623f840c9cdalton */ 2477b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic constexpr BlendFormula MakeCoverageSrcCoeffZeroFormula( 2487b29749c13deab4588cbe0414a93191326800712Brian Salomon BlendFormula::OutputType oneMinusDstCoeffModulateOutput) { 2497b29749c13deab4588cbe0414a93191326800712Brian Salomon return BlendFormula(oneMinusDstCoeffModulateOutput, BlendFormula::kNone_OutputType, 2507b29749c13deab4588cbe0414a93191326800712Brian Salomon kReverseSubtract_GrBlendEquation, kDC_GrBlendCoeff, kOne_GrBlendCoeff); 2517b29749c13deab4588cbe0414a93191326800712Brian Salomon} 2526fd158ea47472c4d038e48980a95e36623f840c9cdalton 2536fd158ea47472c4d038e48980a95e36623f840c9cdalton/** 2546fd158ea47472c4d038e48980a95e36623f840c9cdalton * When there is coverage and the dst coeff is Zero, the equation with f=coverage becomes: 2556fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2566fd158ea47472c4d038e48980a95e36623f840c9cdalton * D' = f * S * srcCoeff + (1-f) * D 2576fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2586fd158ea47472c4d038e48980a95e36623f840c9cdalton * To implement this formula, we output [f] for the secondary color and replace the HW dst coeff 2596fd158ea47472c4d038e48980a95e36623f840c9cdalton * with IS2A. (Note that we can avoid dual source blending when Sa=1 by using ISA.) 2606fd158ea47472c4d038e48980a95e36623f840c9cdalton * 2616fd158ea47472c4d038e48980a95e36623f840c9cdalton * Xfer modes (Sa!=1): src, src-in, src-out 2626fd158ea47472c4d038e48980a95e36623f840c9cdalton */ 2637b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic constexpr BlendFormula MakeCoverageDstCoeffZeroFormula(GrBlendCoeff srcCoeff) { 2647b29749c13deab4588cbe0414a93191326800712Brian Salomon return BlendFormula(BlendFormula::kModulate_OutputType, BlendFormula::kCoverage_OutputType, 2657b29749c13deab4588cbe0414a93191326800712Brian Salomon kAdd_GrBlendEquation, srcCoeff, kIS2A_GrBlendCoeff); 2667b29749c13deab4588cbe0414a93191326800712Brian Salomon} 2677b29749c13deab4588cbe0414a93191326800712Brian Salomon 2687b29749c13deab4588cbe0414a93191326800712Brian Salomon// Older GCC won't like the constexpr arrays because of 2697b29749c13deab4588cbe0414a93191326800712Brian Salomon// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61484. 270f86d3680b19f05b43a2404bbc87db14133047829Bruce Dawson// MSVC 2015 crashes with an internal compiler error. 271f86d3680b19f05b43a2404bbc87db14133047829Bruce Dawson#if !defined(__clang__) && ((defined(__GNUC__) && __GNUC__ < 5) || (defined(_MSC_VER) && _MSC_VER <= 1910)) 2727b29749c13deab4588cbe0414a93191326800712Brian Salomon# define MAYBE_CONSTEXPR const 2737b29749c13deab4588cbe0414a93191326800712Brian Salomon#else 2747b29749c13deab4588cbe0414a93191326800712Brian Salomon# define MAYBE_CONSTEXPR constexpr 2757b29749c13deab4588cbe0414a93191326800712Brian Salomon#endif 2766fd158ea47472c4d038e48980a95e36623f840c9cdalton 2776fd158ea47472c4d038e48980a95e36623f840c9cdalton/** 2786fd158ea47472c4d038e48980a95e36623f840c9cdalton * This table outlines the blend formulas we will use with each xfermode, with and without coverage, 2796fd158ea47472c4d038e48980a95e36623f840c9cdalton * with and without an opaque input color. Optimization properties are deduced at compile time so we 2806fd158ea47472c4d038e48980a95e36623f840c9cdalton * can make runtime decisions quickly. RGB coverage is not supported. 2816fd158ea47472c4d038e48980a95e36623f840c9cdalton */ 2827b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic MAYBE_CONSTEXPR BlendFormula gBlendTable[2][2][(int)SkBlendMode::kLastCoeffMode + 1] = { 2836fd158ea47472c4d038e48980a95e36623f840c9cdalton /*>> No coverage, input color unknown <<*/ {{ 2846fd158ea47472c4d038e48980a95e36623f840c9cdalton 2857b29749c13deab4588cbe0414a93191326800712Brian Salomon /* clear */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 2867b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kZero_GrBlendCoeff), 2877b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 2887b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 2897b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 2907b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 2917b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kSA_GrBlendCoeff), 2927b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 2937b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff), 2947b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 2957b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kSA_GrBlendCoeff), 2967b29749c13deab4588cbe0414a93191326800712Brian Salomon /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 2977b29749c13deab4588cbe0414a93191326800712Brian Salomon /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 2987b29749c13deab4588cbe0414a93191326800712Brian Salomon /* modulate */ MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff), 2997b29749c13deab4588cbe0414a93191326800712Brian Salomon /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 3006fd158ea47472c4d038e48980a95e36623f840c9cdalton 3016fd158ea47472c4d038e48980a95e36623f840c9cdalton }, /*>> Has coverage, input color unknown <<*/ { 3026fd158ea47472c4d038e48980a95e36623f840c9cdalton 3037b29749c13deab4588cbe0414a93191326800712Brian Salomon /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 3047b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src */ MakeCoverageDstCoeffZeroFormula(kOne_GrBlendCoeff), 3057b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 3067b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 3077b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 3087b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-in */ MakeCoverageDstCoeffZeroFormula(kDA_GrBlendCoeff), 3097b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-in */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType), 3107b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-out */ MakeCoverageDstCoeffZeroFormula(kIDA_GrBlendCoeff), 3117b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kISA_GrBlendCoeff), 3127b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 3137b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-atop */ MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), 3147b29749c13deab4588cbe0414a93191326800712Brian Salomon /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 3157b29749c13deab4588cbe0414a93191326800712Brian Salomon /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 3167b29749c13deab4588cbe0414a93191326800712Brian Salomon /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 3177b29749c13deab4588cbe0414a93191326800712Brian Salomon /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 3186fd158ea47472c4d038e48980a95e36623f840c9cdalton 3196fd158ea47472c4d038e48980a95e36623f840c9cdalton }}, /*>> No coverage, input color opaque <<*/ {{ 3206fd158ea47472c4d038e48980a95e36623f840c9cdalton 3217b29749c13deab4588cbe0414a93191326800712Brian Salomon /* clear */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 3227b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kZero_GrBlendCoeff), 3237b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 32428207df02b3dee83141520adf23df2c6aa087860Brian Salomon /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), // see comment below 3257b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 3267b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 3277b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 3287b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 3297b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-out */ MakeCoeffFormula(kZero_GrBlendCoeff, kZero_GrBlendCoeff), 3307b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kZero_GrBlendCoeff), 3317b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 3327b29749c13deab4588cbe0414a93191326800712Brian Salomon /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kZero_GrBlendCoeff), 3337b29749c13deab4588cbe0414a93191326800712Brian Salomon /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 3347b29749c13deab4588cbe0414a93191326800712Brian Salomon /* modulate */ MakeCoeffFormula(kZero_GrBlendCoeff, kSC_GrBlendCoeff), 3357b29749c13deab4588cbe0414a93191326800712Brian Salomon /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 3366fd158ea47472c4d038e48980a95e36623f840c9cdalton 3376fd158ea47472c4d038e48980a95e36623f840c9cdalton }, /*>> Has coverage, input color opaque <<*/ { 3386fd158ea47472c4d038e48980a95e36623f840c9cdalton 3397b29749c13deab4588cbe0414a93191326800712Brian Salomon /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 3407b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 3417b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 3427b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-over */ MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff), 3437b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 3447b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-in */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 3457b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-in */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 3467b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-out */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 3477b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-out */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 3487b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-atop */ MakeCoeffFormula(kDA_GrBlendCoeff, kISA_GrBlendCoeff), 3497b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-atop */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 3507b29749c13deab4588cbe0414a93191326800712Brian Salomon /* xor */ MakeCoeffFormula(kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 3517b29749c13deab4588cbe0414a93191326800712Brian Salomon /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 3527b29749c13deab4588cbe0414a93191326800712Brian Salomon /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 3537b29749c13deab4588cbe0414a93191326800712Brian Salomon /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 3546fd158ea47472c4d038e48980a95e36623f840c9cdalton}}}; 35528207df02b3dee83141520adf23df2c6aa087860Brian Salomon// In the above table src-over is not optimized to src mode when the color is opaque because we 35628207df02b3dee83141520adf23df2c6aa087860Brian Salomon// found no advantage to doing so. Also, we are using a global src-over XP in most cases which is 35728207df02b3dee83141520adf23df2c6aa087860Brian Salomon// not specialized for opaque input. If the table were set to use the src formula then we'd have to 35828207df02b3dee83141520adf23df2c6aa087860Brian Salomon// change when we use this global XP to keep analysis and practice in sync. 3596fd158ea47472c4d038e48980a95e36623f840c9cdalton 3607b29749c13deab4588cbe0414a93191326800712Brian Salomonstatic MAYBE_CONSTEXPR BlendFormula gLCDBlendTable[(int)SkBlendMode::kLastCoeffMode + 1] = { 3617b29749c13deab4588cbe0414a93191326800712Brian Salomon /* clear */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kCoverage_OutputType), 3627b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kOne_GrBlendCoeff), 3637b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst */ MakeCoeffFormula(kZero_GrBlendCoeff, kOne_GrBlendCoeff), 3647b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-over */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kOne_GrBlendCoeff), 3657b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-over */ MakeCoeffFormula(kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 3667b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-in */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kDA_GrBlendCoeff), 3677b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-in */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISAModulate_OutputType), 3687b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-out */ MakeCoverageFormula(BlendFormula::kCoverage_OutputType, kIDA_GrBlendCoeff), 3697b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-out */ MakeSAModulateFormula(kZero_GrBlendCoeff, kISC_GrBlendCoeff), 3707b29749c13deab4588cbe0414a93191326800712Brian Salomon /* src-atop */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kDA_GrBlendCoeff), 3717b29749c13deab4588cbe0414a93191326800712Brian Salomon /* dst-atop */ MakeCoverageFormula(BlendFormula::kISAModulate_OutputType, kIDA_GrBlendCoeff), 3727b29749c13deab4588cbe0414a93191326800712Brian Salomon /* xor */ MakeCoverageFormula(BlendFormula::kSAModulate_OutputType, kIDA_GrBlendCoeff), 3737b29749c13deab4588cbe0414a93191326800712Brian Salomon /* plus */ MakeCoeffFormula(kOne_GrBlendCoeff, kOne_GrBlendCoeff), 3747b29749c13deab4588cbe0414a93191326800712Brian Salomon /* modulate */ MakeCoverageSrcCoeffZeroFormula(BlendFormula::kISCModulate_OutputType), 3757b29749c13deab4588cbe0414a93191326800712Brian Salomon /* screen */ MakeCoeffFormula(kOne_GrBlendCoeff, kISC_GrBlendCoeff), 376723b0501e22373bb3e6c306daaceae02cda8a124egdaniel}; 377723b0501e22373bb3e6c306daaceae02cda8a124egdaniel 3787b29749c13deab4588cbe0414a93191326800712Brian Salomon#undef MAYBE_CONSTEXPR 3797b29749c13deab4588cbe0414a93191326800712Brian Salomon 3805be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomonstatic BlendFormula get_blend_formula(bool isOpaque, 3815be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomon bool hasCoverage, 38286ae0a9e465f157eaa263ef7515e10619946ff83cdalton bool hasMixedSamples, 3837d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode xfermode) { 3847d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode); 3855be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomon bool conflatesCoverage = hasCoverage || hasMixedSamples; 3865be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomon return gBlendTable[isOpaque][conflatesCoverage][(int)xfermode]; 3876fd158ea47472c4d038e48980a95e36623f840c9cdalton} 3886fd158ea47472c4d038e48980a95e36623f840c9cdalton 3895be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomonstatic BlendFormula get_lcd_blend_formula(SkBlendMode xfermode) { 3907d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkASSERT((unsigned)xfermode <= (unsigned)SkBlendMode::kLastCoeffMode); 391723b0501e22373bb3e6c306daaceae02cda8a124egdaniel 3927d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed return gLCDBlendTable[(int)xfermode]; 393723b0501e22373bb3e6c306daaceae02cda8a124egdaniel} 394723b0501e22373bb3e6c306daaceae02cda8a124egdaniel 3956fd158ea47472c4d038e48980a95e36623f840c9cdalton/////////////////////////////////////////////////////////////////////////////// 3966fd158ea47472c4d038e48980a95e36623f840c9cdalton 3976fd158ea47472c4d038e48980a95e36623f840c9cdaltonclass PorterDuffXferProcessor : public GrXferProcessor { 3986fd158ea47472c4d038e48980a95e36623f840c9cdaltonpublic: 3996ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel PorterDuffXferProcessor(BlendFormula blendFormula, GrProcessorAnalysisCoverage coverage) 400abff956455637b12eab374fd44b99e1338799113Ethan Nicholas : INHERITED(kPorterDuffXferProcessor_ClassID, false, false, coverage) 4016ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel , fBlendFormula(blendFormula) { 4026fd158ea47472c4d038e48980a95e36623f840c9cdalton } 4036fd158ea47472c4d038e48980a95e36623f840c9cdalton 4046fd158ea47472c4d038e48980a95e36623f840c9cdalton const char* name() const override { return "Porter Duff"; } 4056fd158ea47472c4d038e48980a95e36623f840c9cdalton 40657d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrGLSLXferProcessor* createGLSLInstance() const override; 4076fd158ea47472c4d038e48980a95e36623f840c9cdalton 4086fd158ea47472c4d038e48980a95e36623f840c9cdalton BlendFormula getBlendFormula() const { return fBlendFormula; } 409f4f2b442228ca188cfb6b44ee3faa86773bb9db3cdalton 410f4f2b442228ca188cfb6b44ee3faa86773bb9db3cdaltonprivate: 41194efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; 412f4f2b442228ca188cfb6b44ee3faa86773bb9db3cdalton 413edbb31f7ddea834b8e55ea66587ea8d33adc53facdalton bool onHasSecondaryOutput() const override { return fBlendFormula.hasSecondaryOutput(); } 414edbb31f7ddea834b8e55ea66587ea8d33adc53facdalton 415f4f2b442228ca188cfb6b44ee3faa86773bb9db3cdalton void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 4167b29749c13deab4588cbe0414a93191326800712Brian Salomon blendInfo->fEquation = fBlendFormula.equation(); 4177b29749c13deab4588cbe0414a93191326800712Brian Salomon blendInfo->fSrcBlend = fBlendFormula.srcCoeff(); 4187b29749c13deab4588cbe0414a93191326800712Brian Salomon blendInfo->fDstBlend = fBlendFormula.dstCoeff(); 4196fd158ea47472c4d038e48980a95e36623f840c9cdalton blendInfo->fWriteColor = fBlendFormula.modifiesDst(); 42041d4f09356567ead0216e1a7e4110bd58822b81fegdaniel } 42141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 42236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool onIsEqual(const GrXferProcessor& xpBase) const override { 42341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor>(); 4246fd158ea47472c4d038e48980a95e36623f840c9cdalton return fBlendFormula == xp.fBlendFormula; 42541d4f09356567ead0216e1a7e4110bd58822b81fegdaniel } 42641d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 4276fd158ea47472c4d038e48980a95e36623f840c9cdalton const BlendFormula fBlendFormula; 42841d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 42941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel typedef GrXferProcessor INHERITED; 43041d4f09356567ead0216e1a7e4110bd58822b81fegdaniel}; 43141d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 43241d4f09356567ead0216e1a7e4110bd58822b81fegdaniel/////////////////////////////////////////////////////////////////////////////// 43341d4f09356567ead0216e1a7e4110bd58822b81fegdaniel 4342d721d33aad192cc8a7a1321504b39bdca2a57ceegdanielstatic void append_color_output(const PorterDuffXferProcessor& xp, 4354ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLXPFragmentBuilder* fragBuilder, 4366fd158ea47472c4d038e48980a95e36623f840c9cdalton BlendFormula::OutputType outputType, const char* output, 4376fd158ea47472c4d038e48980a95e36623f840c9cdalton const char* inColor, const char* inCoverage) { 4388c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon SkASSERT(inCoverage); 4398c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon SkASSERT(inColor); 4406fd158ea47472c4d038e48980a95e36623f840c9cdalton switch (outputType) { 4416fd158ea47472c4d038e48980a95e36623f840c9cdalton case BlendFormula::kNone_OutputType: 442f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas fragBuilder->codeAppendf("%s = half4(0.0);", output); 4436fd158ea47472c4d038e48980a95e36623f840c9cdalton break; 4446fd158ea47472c4d038e48980a95e36623f840c9cdalton case BlendFormula::kCoverage_OutputType: 44586ae0a9e465f157eaa263ef7515e10619946ff83cdalton // We can have a coverage formula while not reading coverage if there are mixed samples. 4468c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon fragBuilder->codeAppendf("%s = %s;", output, inCoverage); 4476fd158ea47472c4d038e48980a95e36623f840c9cdalton break; 4486fd158ea47472c4d038e48980a95e36623f840c9cdalton case BlendFormula::kModulate_OutputType: 4498c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCoverage); 4506fd158ea47472c4d038e48980a95e36623f840c9cdalton break; 451723b0501e22373bb3e6c306daaceae02cda8a124egdaniel case BlendFormula::kSAModulate_OutputType: 4528c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inCoverage); 453723b0501e22373bb3e6c306daaceae02cda8a124egdaniel break; 4546fd158ea47472c4d038e48980a95e36623f840c9cdalton case BlendFormula::kISAModulate_OutputType: 4558c852be264d003b2e610c5b8634bc0f81c46bbbaBrian Salomon fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inColor, inCoverage); 4566fd158ea47472c4d038e48980a95e36623f840c9cdalton break; 4576fd158ea47472c4d038e48980a95e36623f840c9cdalton case BlendFormula::kISCModulate_OutputType: 458f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas fragBuilder->codeAppendf("%s = (half4(1.0) - %s) * %s;", output, inColor, inCoverage); 4596fd158ea47472c4d038e48980a95e36623f840c9cdalton break; 4606fd158ea47472c4d038e48980a95e36623f840c9cdalton default: 461b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner SK_ABORT("Unsupported output type."); 4626fd158ea47472c4d038e48980a95e36623f840c9cdalton break; 4633ad6570e94965d54871eaea8b314f560b82ca792egdaniel } 4643ad6570e94965d54871eaea8b314f560b82ca792egdaniel} 4653ad6570e94965d54871eaea8b314f560b82ca792egdaniel 466fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdanielclass GLPorterDuffXferProcessor : public GrGLSLXferProcessor { 46741d4f09356567ead0216e1a7e4110bd58822b81fegdanielpublic: 4686fd158ea47472c4d038e48980a95e36623f840c9cdalton static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) { 46941d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcessor>(); 4707b29749c13deab4588cbe0414a93191326800712Brian Salomon b->add32(xp.getBlendFormula().primaryOutput() | 4717b29749c13deab4588cbe0414a93191326800712Brian Salomon (xp.getBlendFormula().secondaryOutput() << 3)); 4726fd158ea47472c4d038e48980a95e36623f840c9cdalton GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8); 473fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein } 47450785a3d10b53bea5beb6e18431a2449860be237bsalomon 47550785a3d10b53bea5beb6e18431a2449860be237bsalomonprivate: 476edbb31f7ddea834b8e55ea66587ea8d33adc53facdalton void emitOutputsForBlendState(const EmitArgs& args) override { 47741d4f09356567ead0216e1a7e4110bd58822b81fegdaniel const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcessor>(); 4784ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 479c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman 4806fd158ea47472c4d038e48980a95e36623f840c9cdalton BlendFormula blendFormula = xp.getBlendFormula(); 4816fd158ea47472c4d038e48980a95e36623f840c9cdalton if (blendFormula.hasSecondaryOutput()) { 4827b29749c13deab4588cbe0414a93191326800712Brian Salomon append_color_output(xp, fragBuilder, blendFormula.secondaryOutput(), 4836fd158ea47472c4d038e48980a95e36623f840c9cdalton args.fOutputSecondary, args.fInputColor, args.fInputCoverage); 484c230414861558ce20b74281b1ca363e56c441832egdaniel } 4857b29749c13deab4588cbe0414a93191326800712Brian Salomon append_color_output(xp, fragBuilder, blendFormula.primaryOutput(), args.fOutputPrimary, 4867b29749c13deab4588cbe0414a93191326800712Brian Salomon args.fInputColor, args.fInputCoverage); 487378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel } 488378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel 489018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {} 490378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel 491fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdaniel typedef GrGLSLXferProcessor INHERITED; 492378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel}; 493378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel 494378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel/////////////////////////////////////////////////////////////////////////////// 495378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel 49694efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomonvoid PorterDuffXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, 49757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 4986fd158ea47472c4d038e48980a95e36623f840c9cdalton GLPorterDuffXferProcessor::GenKey(*this, b); 499eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt} 500eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 50157d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const { 502385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new GLPorterDuffXferProcessor; 503378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel} 504378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel 5056fd158ea47472c4d038e48980a95e36623f840c9cdalton/////////////////////////////////////////////////////////////////////////////// 5066fd158ea47472c4d038e48980a95e36623f840c9cdalton 5076fd158ea47472c4d038e48980a95e36623f840c9cdaltonclass ShaderPDXferProcessor : public GrXferProcessor { 5086fd158ea47472c4d038e48980a95e36623f840c9cdaltonpublic: 5096ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel ShaderPDXferProcessor(bool hasMixedSamples, SkBlendMode xfermode, 5106ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel GrProcessorAnalysisCoverage coverage) 511abff956455637b12eab374fd44b99e1338799113Ethan Nicholas : INHERITED(kShaderPDXferProcessor_ClassID, true, hasMixedSamples, coverage) 512abff956455637b12eab374fd44b99e1338799113Ethan Nicholas , fXfermode(xfermode) { 513c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman } 514c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman 5156fd158ea47472c4d038e48980a95e36623f840c9cdalton const char* name() const override { return "Porter Duff Shader"; } 5166fd158ea47472c4d038e48980a95e36623f840c9cdalton 51757d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrGLSLXferProcessor* createGLSLInstance() const override; 5186fd158ea47472c4d038e48980a95e36623f840c9cdalton 5197d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode getXfermode() const { return fXfermode; } 5206fd158ea47472c4d038e48980a95e36623f840c9cdalton 5216fd158ea47472c4d038e48980a95e36623f840c9cdaltonprivate: 52294efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; 5236fd158ea47472c4d038e48980a95e36623f840c9cdalton 5246fd158ea47472c4d038e48980a95e36623f840c9cdalton bool onIsEqual(const GrXferProcessor& xpBase) const override { 5256fd158ea47472c4d038e48980a95e36623f840c9cdalton const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>(); 5266fd158ea47472c4d038e48980a95e36623f840c9cdalton return fXfermode == xp.fXfermode; 5273ad6570e94965d54871eaea8b314f560b82ca792egdaniel } 5288750924a1470e8215b2a344155259b93062d3fa2egdaniel 5297d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed const SkBlendMode fXfermode; 5306fd158ea47472c4d038e48980a95e36623f840c9cdalton 5316fd158ea47472c4d038e48980a95e36623f840c9cdalton typedef GrXferProcessor INHERITED; 5326fd158ea47472c4d038e48980a95e36623f840c9cdalton}; 5336fd158ea47472c4d038e48980a95e36623f840c9cdalton 5346fd158ea47472c4d038e48980a95e36623f840c9cdalton/////////////////////////////////////////////////////////////////////////////// 5356fd158ea47472c4d038e48980a95e36623f840c9cdalton 536fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdanielclass GLShaderPDXferProcessor : public GrGLSLXferProcessor { 5376fd158ea47472c4d038e48980a95e36623f840c9cdaltonpublic: 5386fd158ea47472c4d038e48980a95e36623f840c9cdalton static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) { 5396fd158ea47472c4d038e48980a95e36623f840c9cdalton const ShaderPDXferProcessor& xp = processor.cast<ShaderPDXferProcessor>(); 5407d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed b->add32((int)xp.getXfermode()); 541c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman } 542c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman 5436fd158ea47472c4d038e48980a95e36623f840c9cdaltonprivate: 5447ea439b2203855db97330b25945b87dd4b170b8begdaniel void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder, 5457ea439b2203855db97330b25945b87dd4b170b8begdaniel GrGLSLUniformHandler* uniformHandler, 5464ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel const char* srcColor, 547f34b293681ea49aaa4aaa70d84515e4a58a112e7egdaniel const char* srcCoverage, 5484ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel const char* dstColor, 5494ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel const char* outColor, 550f34b293681ea49aaa4aaa70d84515e4a58a112e7egdaniel const char* outColorSecondary, 5514ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel const GrXferProcessor& proc) override { 552edbb31f7ddea834b8e55ea66587ea8d33adc53facdalton const ShaderPDXferProcessor& xp = proc.cast<ShaderPDXferProcessor>(); 553c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman 5544ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, outColor, xp.getXfermode()); 555f34b293681ea49aaa4aaa70d84515e4a58a112e7egdaniel 556f34b293681ea49aaa4aaa70d84515e4a58a112e7egdaniel // Apply coverage. 557f42fca4027ed4f235ef927786813a5ed0e6652b9robertphillips INHERITED::DefaultCoverageModulation(fragBuilder, srcCoverage, dstColor, outColor, 558f42fca4027ed4f235ef927786813a5ed0e6652b9robertphillips outColorSecondary, xp); 559c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman } 560c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman 561018fb62d12d1febf121fe265da5b6117b86a6541egdaniel void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {} 562c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman 563fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdaniel typedef GrGLSLXferProcessor INHERITED; 5646fd158ea47472c4d038e48980a95e36623f840c9cdalton}; 5656fd158ea47472c4d038e48980a95e36623f840c9cdalton 5666fd158ea47472c4d038e48980a95e36623f840c9cdalton/////////////////////////////////////////////////////////////////////////////// 5679513143efa734bef0c1a0c7f945022572dbc8518egdaniel 56894efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomonvoid ShaderPDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&, 56957d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 5706fd158ea47472c4d038e48980a95e36623f840c9cdalton GLShaderPDXferProcessor::GenKey(*this, b); 571c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman} 572c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman 57357d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLXferProcessor* ShaderPDXferProcessor::createGLSLInstance() const { 574385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new GLShaderPDXferProcessor; 575c230414861558ce20b74281b1ca363e56c441832egdaniel} 576c230414861558ce20b74281b1ca363e56c441832egdaniel 577378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel/////////////////////////////////////////////////////////////////////////////// 578378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel 5790d5fd110e0b7ce9b892833d874145a79ca67da8degdanielclass PDLCDXferProcessor : public GrXferProcessor { 5800d5fd110e0b7ce9b892833d874145a79ca67da8degdanielpublic: 581d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomon static sk_sp<const GrXferProcessor> Make(SkBlendMode mode, 582d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomon const GrProcessorAnalysisColor& inputColor); 5830d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 5840d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel ~PDLCDXferProcessor() override; 5850d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 5860d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel const char* name() const override { return "Porter Duff LCD"; } 5870d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 58857d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrGLSLXferProcessor* createGLSLInstance() const override; 5890d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 5901c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon uint8_t alpha() const { return fAlpha; } 5911c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon 5920d5fd110e0b7ce9b892833d874145a79ca67da8degdanielprivate: 5930d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha); 5940d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 59594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override; 5960d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 5970d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 5980d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel blendInfo->fSrcBlend = kConstC_GrBlendCoeff; 5990d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel blendInfo->fDstBlend = kISC_GrBlendCoeff; 6000d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel blendInfo->fBlendConstant = fBlendConstant; 6010d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel } 6020d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6030d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel bool onIsEqual(const GrXferProcessor& xpBase) const override { 6040d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel const PDLCDXferProcessor& xp = xpBase.cast<PDLCDXferProcessor>(); 6051c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon if (fBlendConstant != xp.fBlendConstant || fAlpha != xp.fAlpha) { 6060d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel return false; 6070d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel } 6080d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel return true; 6090d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel } 6100d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6111c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon GrColor fBlendConstant; 6121c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon uint8_t fAlpha; 6130d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6140d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel typedef GrXferProcessor INHERITED; 6150d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel}; 6160d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6170d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel/////////////////////////////////////////////////////////////////////////////// 6180d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 619fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdanielclass GLPDLCDXferProcessor : public GrGLSLXferProcessor { 6200d5fd110e0b7ce9b892833d874145a79ca67da8degdanielpublic: 6211c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon GLPDLCDXferProcessor(const GrProcessor&) : fLastAlpha(SK_MaxU32) {} 6220d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 623d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon ~GLPDLCDXferProcessor() override {} 6240d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 62594efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon static void GenKey(const GrProcessor& processor, const GrShaderCaps& caps, 6260d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel GrProcessorKeyBuilder* b) {} 6270d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6280d5fd110e0b7ce9b892833d874145a79ca67da8degdanielprivate: 629edbb31f7ddea834b8e55ea66587ea8d33adc53facdalton void emitOutputsForBlendState(const EmitArgs& args) override { 6301c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon const char* alpha; 631f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas fAlphaUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, 632f7b8820dc813d1eb0b6b43fe4581dded0da38cafEthan Nicholas "alpha", &alpha); 6334ca2e6034365ad280ec64473f7f1d72ebd8335e4egdaniel GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; 6341c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon // We want to force our primary output to be alpha * Coverage, where alpha is the alpha 6351c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon // value of the src color. We know that there are no color stages (or we wouldn't have 6361c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon // created this xp) and the r,g, and b channels of the op's input color are baked into the 6371c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon // blend constant. 63856cf6dcb6572f1d355af041c1ebf157b2b3d0165egdaniel SkASSERT(args.fInputCoverage); 6391c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, alpha, args.fInputCoverage); 6400d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel } 6410d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6421c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon void onSetData(const GrGLSLProgramDataManager& pdm, const GrXferProcessor& xp) override { 6431c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon uint32_t alpha = SkToU32(xp.cast<PDLCDXferProcessor>().alpha()); 6441c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon if (fLastAlpha != alpha) { 6451c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon pdm.set1f(fAlphaUniform, alpha / 255.f); 6461c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon fLastAlpha = alpha; 6471c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon } 6481c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon } 6490d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6501c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon GrGLSLUniformHandler::UniformHandle fAlphaUniform; 6511c10fddd1f563412f501e49db1d21844c4d5b058Brian Salomon uint32_t fLastAlpha; 652fa4cc8bf2aa782431609dd2ac16b1fc36de72e44egdaniel typedef GrGLSLXferProcessor INHERITED; 6530d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel}; 6540d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6550d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel/////////////////////////////////////////////////////////////////////////////// 6560d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6570d5fd110e0b7ce9b892833d874145a79ca67da8degdanielPDLCDXferProcessor::PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha) 658abff956455637b12eab374fd44b99e1338799113Ethan Nicholas : INHERITED(kPDLCDXferProcessor_ClassID, false, false, GrProcessorAnalysisCoverage::kLCD) 6596ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel , fBlendConstant(blendConstant) 6600d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel , fAlpha(alpha) { 6610d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel} 6620d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 663d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomonsk_sp<const GrXferProcessor> PDLCDXferProcessor::Make(SkBlendMode mode, 664d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomon const GrProcessorAnalysisColor& color) { 665d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomon if (SkBlendMode::kSrcOver != mode) { 66696fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 6670d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel } 668eec6f7be5461e588210f383b8af18f324a2bdb46Brian Salomon GrColor blendConstant; 6691c6025cc9da4a4f3a8ad16dde2ae8dcf120ed270Brian Salomon if (!color.isConstant(&blendConstant)) { 67096fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 6710d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel } 672afb41033efae3f5c71cac8c6127236efab613125Brian Salomon blendConstant = GrUnpremulColor(blendConstant); 6730d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel uint8_t alpha = GrColorUnpackA(blendConstant); 6740d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel blendConstant |= (0xff << GrColor_SHIFT_A); 675a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon return sk_sp<GrXferProcessor>(new PDLCDXferProcessor(blendConstant, alpha)); 6760d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel} 6770d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6780d5fd110e0b7ce9b892833d874145a79ca67da8degdanielPDLCDXferProcessor::~PDLCDXferProcessor() { 6790d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel} 6800d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 68194efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomonvoid PDLCDXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps, 68257d3b039c635945e1dc2fcbac3462ed8bfedb068egdaniel GrProcessorKeyBuilder* b) const { 683cc25297364433ad66450faf391e599274ed4bc7degdaniel GLPDLCDXferProcessor::GenKey(*this, caps, b); 6840d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel} 6850d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 68657d3b039c635945e1dc2fcbac3462ed8bfedb068egdanielGrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const { 687385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary return new GLPDLCDXferProcessor(*this); 6880d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel} 6890d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel 6900d5fd110e0b7ce9b892833d874145a79ca67da8degdaniel/////////////////////////////////////////////////////////////////////////////// 6916fd158ea47472c4d038e48980a95e36623f840c9cdalton 692a16339297859f37df69230e64f05624cef511ad3Brian Salomonconstexpr GrPorterDuffXPFactory::GrPorterDuffXPFactory(SkBlendMode xfermode) 693a16339297859f37df69230e64f05624cef511ad3Brian Salomon : fBlendMode(xfermode) {} 694a16339297859f37df69230e64f05624cef511ad3Brian Salomon 695a16339297859f37df69230e64f05624cef511ad3Brian Salomonconst GrXPFactory* GrPorterDuffXPFactory::Get(SkBlendMode blendMode) { 696a16339297859f37df69230e64f05624cef511ad3Brian Salomon SkASSERT((unsigned)blendMode <= (unsigned)SkBlendMode::kLastCoeffMode); 697a16339297859f37df69230e64f05624cef511ad3Brian Salomon 698a16339297859f37df69230e64f05624cef511ad3Brian Salomon // If these objects are constructed as static constexpr by cl.exe (2015 SP2) the vtables are 699a16339297859f37df69230e64f05624cef511ad3Brian Salomon // null. 700a16339297859f37df69230e64f05624cef511ad3Brian Salomon#ifdef SK_BUILD_FOR_WIN 701a16339297859f37df69230e64f05624cef511ad3Brian Salomon#define _CONSTEXPR_ 702a16339297859f37df69230e64f05624cef511ad3Brian Salomon#else 703a16339297859f37df69230e64f05624cef511ad3Brian Salomon#define _CONSTEXPR_ constexpr 704a16339297859f37df69230e64f05624cef511ad3Brian Salomon#endif 705a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gClearPDXPF(SkBlendMode::kClear); 706a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcPDXPF(SkBlendMode::kSrc); 707a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gDstPDXPF(SkBlendMode::kDst); 708a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOverPDXPF(SkBlendMode::kSrcOver); 709a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOverPDXPF(SkBlendMode::kDstOver); 710a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcInPDXPF(SkBlendMode::kSrcIn); 711a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gDstInPDXPF(SkBlendMode::kDstIn); 712a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcOutPDXPF(SkBlendMode::kSrcOut); 713a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gDstOutPDXPF(SkBlendMode::kDstOut); 714a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gSrcATopPDXPF(SkBlendMode::kSrcATop); 715a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gDstATopPDXPF(SkBlendMode::kDstATop); 716a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gXorPDXPF(SkBlendMode::kXor); 717a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gPlusPDXPF(SkBlendMode::kPlus); 718a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gModulatePDXPF(SkBlendMode::kModulate); 719a16339297859f37df69230e64f05624cef511ad3Brian Salomon static _CONSTEXPR_ const GrPorterDuffXPFactory gScreenPDXPF(SkBlendMode::kScreen); 720a16339297859f37df69230e64f05624cef511ad3Brian Salomon#undef _CONSTEXPR_ 721a16339297859f37df69230e64f05624cef511ad3Brian Salomon 722a16339297859f37df69230e64f05624cef511ad3Brian Salomon switch (blendMode) { 723a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kClear: 724a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gClearPDXPF; 725a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kSrc: 726a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gSrcPDXPF; 727a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kDst: 728a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gDstPDXPF; 729a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kSrcOver: 730a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gSrcOverPDXPF; 731a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kDstOver: 732a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gDstOverPDXPF; 733a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kSrcIn: 734a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gSrcInPDXPF; 735a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kDstIn: 736a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gDstInPDXPF; 737a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kSrcOut: 738a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gSrcOutPDXPF; 739a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kDstOut: 740a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gDstOutPDXPF; 741a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kSrcATop: 742a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gSrcATopPDXPF; 743a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kDstATop: 744a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gDstATopPDXPF; 745a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kXor: 746a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gXorPDXPF; 747a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kPlus: 748a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gPlusPDXPF; 749a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kModulate: 750a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gModulatePDXPF; 751a16339297859f37df69230e64f05624cef511ad3Brian Salomon case SkBlendMode::kScreen: 752a16339297859f37df69230e64f05624cef511ad3Brian Salomon return &gScreenPDXPF; 753a16339297859f37df69230e64f05624cef511ad3Brian Salomon default: 754b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner SK_ABORT("Unexpected blend mode."); 755a16339297859f37df69230e64f05624cef511ad3Brian Salomon return nullptr; 756c016fb8f9fb53dd8d4936c5e9e16a9dc99ab392eegdaniel } 757c016fb8f9fb53dd8d4936c5e9e16a9dc99ab392eegdaniel} 758c016fb8f9fb53dd8d4936c5e9e16a9dc99ab392eegdaniel 759d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomonsk_sp<const GrXferProcessor> GrPorterDuffXPFactory::makeXferProcessor( 760a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage, 7619a725dd9485654155e2e4196c32d372360bcdb61Brian Osman bool hasMixedSamples, const GrCaps& caps, GrPixelConfigIsClamped dstIsClamped) const { 762723b0501e22373bb3e6c306daaceae02cda8a124egdaniel BlendFormula blendFormula; 7636ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel bool isLCD = coverage == GrProcessorAnalysisCoverage::kLCD; 7646ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel if (isLCD) { 765d7b1159d787de27d75032ec213903a03962ec839Greg Daniel // See comment in MakeSrcOverXferProcessor about color.isOpaque here 766d7b1159d787de27d75032ec213903a03962ec839Greg Daniel if (SkBlendMode::kSrcOver == fBlendMode && color.isConstant() && /*color.isOpaque() &&*/ 767e73f1f6dfa665802a942e743a227b5c98bc958dbegdaniel !caps.shaderCaps()->dualSourceBlendingSupport() && 768e73f1f6dfa665802a942e743a227b5c98bc958dbegdaniel !caps.shaderCaps()->dstReadInShaderSupport()) { 769e73f1f6dfa665802a942e743a227b5c98bc958dbegdaniel // If we don't have dual source blending or in shader dst reads, we fall back to this 770e73f1f6dfa665802a942e743a227b5c98bc958dbegdaniel // trick for rendering SrcOver LCD text instead of doing a dst copy. 771a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon return PDLCDXferProcessor::Make(fBlendMode, color); 772723b0501e22373bb3e6c306daaceae02cda8a124egdaniel } 7735be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomon blendFormula = get_lcd_blend_formula(fBlendMode); 774723b0501e22373bb3e6c306daaceae02cda8a124egdaniel } else { 7751c6025cc9da4a4f3a8ad16dde2ae8dcf120ed270Brian Salomon blendFormula = 776a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon get_blend_formula(color.isOpaque(), GrProcessorAnalysisCoverage::kNone != coverage, 7771c6025cc9da4a4f3a8ad16dde2ae8dcf120ed270Brian Salomon hasMixedSamples, fBlendMode); 7786fd158ea47472c4d038e48980a95e36623f840c9cdalton } 7796fd158ea47472c4d038e48980a95e36623f840c9cdalton 7809a725dd9485654155e2e4196c32d372360bcdb61Brian Osman bool needsClamp = SkBlendMode::kPlus == fBlendMode; 7816ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel if ((blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport()) || 7829a725dd9485654155e2e4196c32d372360bcdb61Brian Osman (isLCD && (SkBlendMode::kSrcOver != fBlendMode /*|| !color.isOpaque()*/)) || 7839a725dd9485654155e2e4196c32d372360bcdb61Brian Osman (needsClamp && (GrPixelConfigIsClamped::kNo == dstIsClamped))) { 7846ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel return sk_sp<const GrXferProcessor>(new ShaderPDXferProcessor(hasMixedSamples, fBlendMode, 7856ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel coverage)); 7869513143efa734bef0c1a0c7f945022572dbc8518egdaniel } 7876ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel return sk_sp<const GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage)); 788378092f3d10b1dd62967f419c35cfefec7c10ee7egdaniel} 7899513143efa734bef0c1a0c7f945022572dbc8518egdaniel 790318538484f99253b6a2acf97d4d1b420e628b289Brian Salomonstatic inline GrXPFactory::AnalysisProperties analysis_properties( 791a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon const GrProcessorAnalysisColor& color, const GrProcessorAnalysisCoverage& coverage, 7929a725dd9485654155e2e4196c32d372360bcdb61Brian Osman const GrCaps& caps, GrPixelConfigIsClamped dstIsClamped, SkBlendMode mode) { 793318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon using AnalysisProperties = GrXPFactory::AnalysisProperties; 794318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon AnalysisProperties props = AnalysisProperties::kNone; 795a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon bool hasCoverage = GrProcessorAnalysisCoverage::kNone != coverage; 7966ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel bool isLCD = GrProcessorAnalysisCoverage::kLCD == coverage; 7976ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel BlendFormula formula; 7986ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel if (isLCD) { 7996ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel formula = gLCDBlendTable[(int)mode]; 8006ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel } else { 8016ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel formula = gBlendTable[color.isOpaque()][hasCoverage][(int)mode]; 8026ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel } 80379cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel 80479cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel if (formula.canTweakAlphaForCoverage() && !isLCD) { 805318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon props |= AnalysisProperties::kCompatibleWithAlphaAsCoverage; 806318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon } 80779cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel 80879cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel if (isLCD) { 809aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel // See comment in MakeSrcOverXferProcessor about color.isOpaque here 810aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel if (SkBlendMode::kSrcOver == mode && color.isConstant() && /*color.isOpaque() &&*/ 81179cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel !caps.shaderCaps()->dualSourceBlendingSupport() && 81279cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel !caps.shaderCaps()->dstReadInShaderSupport()) { 81379cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel props |= AnalysisProperties::kIgnoresInputColor; 81479cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel } else { 81579cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel // For LCD blending, if the color is not opaque we must read the dst in shader even if 81679cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel // we have dual source blending. The opaqueness check must be done after blending so for 81779cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel // simplicity we only allow src-over to not take the dst read path (though src, src-in, 81879cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel // and DstATop would also work). We also fall into the dst read case for src-over if we 81979cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel // do not have dual source blending. 82079cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel if (SkBlendMode::kSrcOver != mode || 821d7b1159d787de27d75032ec213903a03962ec839Greg Daniel /*!color.isOpaque() ||*/ // See comment in MakeSrcOverXferProcessor about isOpaque. 822d7b1159d787de27d75032ec213903a03962ec839Greg Daniel (formula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) { 82379cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel props |= AnalysisProperties::kReadsDstInShader; 824318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon } 825723b0501e22373bb3e6c306daaceae02cda8a124egdaniel } 8266ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel } else { 82779cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel // With dual-source blending we never need the destination color in the shader. 82879cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel if (!caps.shaderCaps()->dualSourceBlendingSupport()) { 82979cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel // Mixed samples implicity computes a fractional coverage from sample coverage. This 83079cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel // could affect the formula used. However, we don't expect to have mixed samples without 83179cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel // dual source blending. 83279cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel SkASSERT(!caps.usesMixedSamples()); 83379cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel if (formula.hasSecondaryOutput()) { 83479cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel props |= AnalysisProperties::kReadsDstInShader; 83579cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel } 8366ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel } 837c33db93d1b285923b5deef97ecb04d4d01e05dd5bungeman } 83879cdf28c51c8f8ff83575677419f95c0657fa077Greg Daniel 8399a725dd9485654155e2e4196c32d372360bcdb61Brian Osman bool needsClamp = SkBlendMode::kPlus == mode; 8409a725dd9485654155e2e4196c32d372360bcdb61Brian Osman if (needsClamp && (GrPixelConfigIsClamped::kNo == dstIsClamped)) { 8419a725dd9485654155e2e4196c32d372360bcdb61Brian Osman props |= AnalysisProperties::kReadsDstInShader; 8429a725dd9485654155e2e4196c32d372360bcdb61Brian Osman } 8439a725dd9485654155e2e4196c32d372360bcdb61Brian Osman 844318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon if (!formula.modifiesDst() || !formula.usesInputColor()) { 845318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon props |= AnalysisProperties::kIgnoresInputColor; 846318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon } 847318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon // Ignore the effect of coverage here for overlap stencil and cover property 848318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon auto colorFormula = gBlendTable[color.isOpaque()][0][(int)mode]; 8497b29749c13deab4588cbe0414a93191326800712Brian Salomon SkASSERT(kAdd_GrBlendEquation == colorFormula.equation()); 850318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon if (!colorFormula.usesDstColor()) { 851318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon props |= AnalysisProperties::kCanCombineOverlappedStencilAndCover; 852318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon } 853318538484f99253b6a2acf97d4d1b420e628b289Brian Salomon return props; 85450785a3d10b53bea5beb6e18431a2449860be237bsalomon} 85550785a3d10b53bea5beb6e18431a2449860be237bsalomon 856318538484f99253b6a2acf97d4d1b420e628b289Brian SalomonGrXPFactory::AnalysisProperties GrPorterDuffXPFactory::analysisProperties( 857a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon const GrProcessorAnalysisColor& color, 858a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon const GrProcessorAnalysisCoverage& coverage, 8599a725dd9485654155e2e4196c32d372360bcdb61Brian Osman const GrCaps& caps, 8609a725dd9485654155e2e4196c32d372360bcdb61Brian Osman GrPixelConfigIsClamped dstIsClamped) const { 8619a725dd9485654155e2e4196c32d372360bcdb61Brian Osman return analysis_properties(color, coverage, caps, dstIsClamped, fBlendMode); 862780b41fc10fb212ec6d9a9aeb7ca4cc0292fb85eBrian Salomon} 863780b41fc10fb212ec6d9a9aeb7ca4cc0292fb85eBrian Salomon 864f234272cbdcbcd46be462317e75cd138999c9fe9egdanielGR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); 865c230414861558ce20b74281b1ca363e56c441832egdaniel 8666f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#if GR_TEST_UTILS 867a16339297859f37df69230e64f05624cef511ad3Brian Salomonconst GrXPFactory* GrPorterDuffXPFactory::TestGet(GrProcessorTestData* d) { 8687d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed SkBlendMode mode = SkBlendMode(d->fRandom->nextULessThan((int)SkBlendMode::kLastCoeffMode)); 869a16339297859f37df69230e64f05624cef511ad3Brian Salomon return GrPorterDuffXPFactory::Get(mode); 870c230414861558ce20b74281b1ca363e56c441832egdaniel} 8716f6961ebad65c582318564b3688e78e5c99f3935Hal Canary#endif 8729513143efa734bef0c1a0c7f945022572dbc8518egdaniel 873f234272cbdcbcd46be462317e75cd138999c9fe9egdanielvoid GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, 874f234272cbdcbcd46be462317e75cd138999c9fe9egdaniel int* outPrimary, 875f234272cbdcbcd46be462317e75cd138999c9fe9egdaniel int* outSecondary) { 8766fd158ea47472c4d038e48980a95e36623f840c9cdalton if (!!strcmp(xp->name(), "Porter Duff")) { 8776fd158ea47472c4d038e48980a95e36623f840c9cdalton *outPrimary = *outSecondary = -1; 8786fd158ea47472c4d038e48980a95e36623f840c9cdalton return; 8796fd158ea47472c4d038e48980a95e36623f840c9cdalton } 8806fd158ea47472c4d038e48980a95e36623f840c9cdalton BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)->getBlendFormula(); 8817b29749c13deab4588cbe0414a93191326800712Brian Salomon *outPrimary = blendFormula.primaryOutput(); 8827b29749c13deab4588cbe0414a93191326800712Brian Salomon *outSecondary = blendFormula.secondaryOutput(); 8836fd158ea47472c4d038e48980a95e36623f840c9cdalton} 884c4b72720e75313079212e69e46a5ef7c474b2305egdaniel 885c4b72720e75313079212e69e46a5ef7c474b2305egdaniel//////////////////////////////////////////////////////////////////////////////////////////////// 886c4b72720e75313079212e69e46a5ef7c474b2305egdaniel// SrcOver Global functions 887c4b72720e75313079212e69e46a5ef7c474b2305egdaniel//////////////////////////////////////////////////////////////////////////////////////////////// 8882047b7855546b21f7956c398592c070b3f91a9dbbsalomonconst GrXferProcessor& GrPorterDuffXPFactory::SimpleSrcOverXP() { 8897b29749c13deab4588cbe0414a93191326800712Brian Salomon static BlendFormula gSrcOverBlendFormula = 8907b29749c13deab4588cbe0414a93191326800712Brian Salomon MakeCoeffFormula(kOne_GrBlendCoeff, kISA_GrBlendCoeff); 8916ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula, 8926ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel GrProcessorAnalysisCoverage::kSingleChannel); 8932047b7855546b21f7956c398592c070b3f91a9dbbsalomon return gSrcOverXP; 8942047b7855546b21f7956c398592c070b3f91a9dbbsalomon} 895c4b72720e75313079212e69e46a5ef7c474b2305egdaniel 896d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomonsk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeSrcOverXferProcessor( 897a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon const GrProcessorAnalysisColor& color, GrProcessorAnalysisCoverage coverage, 898a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon bool hasMixedSamples, const GrCaps& caps) { 899abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel // We want to not make an xfer processor if possible. Thus for the simple case where we are not 900abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from 901abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel // the general case where we convert a src-over blend that has solid coverage and an opaque 902abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel // color to src-mode, which allows disabling of blending. 903a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon if (coverage != GrProcessorAnalysisCoverage::kLCD) { 9042047b7855546b21f7956c398592c070b3f91a9dbbsalomon // We return nullptr here, which our caller interprets as meaning "use SimpleSrcOverXP". 9052047b7855546b21f7956c398592c070b3f91a9dbbsalomon // We don't simply return the address of that XP here because our caller would have to unref 9062047b7855546b21f7956c398592c070b3f91a9dbbsalomon // it and since it is a global object and GrProgramElement's ref-cnting system is not thread 9072047b7855546b21f7956c398592c070b3f91a9dbbsalomon // safe. 9082047b7855546b21f7956c398592c070b3f91a9dbbsalomon return nullptr; 90956cf6dcb6572f1d355af041c1ebf157b2b3d0165egdaniel } 91056cf6dcb6572f1d355af041c1ebf157b2b3d0165egdaniel 911aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel // Currently up the stack Skia is requiring that the dst is opaque or that the client has said 912aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel // the opaqueness doesn't matter. Thus for src-over we don't need to worry about the src color 913d7b1159d787de27d75032ec213903a03962ec839Greg Daniel // being opaque or not. This allows us to use faster code paths as well as avoid various bugs 914d7b1159d787de27d75032ec213903a03962ec839Greg Daniel // that occur with dst reads in the shader blending. For now we disable the check for 915d7b1159d787de27d75032ec213903a03962ec839Greg Daniel // opaqueness, but in the future we should pass down the knowledge about dst opaqueness and make 916d7b1159d787de27d75032ec213903a03962ec839Greg Daniel // the correct decision here. 917aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel // 918aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel // This also fixes a chrome bug on macs where we are getting random fuzziness when doing 919aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel // blending in the shader for non opaque sources. 920aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel if (color.isConstant() && /*color.isOpaque() &&*/ 921aa13223f54d1f55ba702582f61359f8b43782730Greg Daniel !caps.shaderCaps()->dualSourceBlendingSupport() && 922abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel !caps.shaderCaps()->dstReadInShaderSupport()) { 923abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel // If we don't have dual source blending or in shader dst reads, we fall 924abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel // back to this trick for rendering SrcOver LCD text instead of doing a 925abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel // dst copy. 926a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon return PDLCDXferProcessor::Make(SkBlendMode::kSrcOver, color); 927c4b72720e75313079212e69e46a5ef7c474b2305egdaniel } 928c4b72720e75313079212e69e46a5ef7c474b2305egdaniel 929abe795e4db533c2e230be0c2be868754e5a02a7eegdaniel BlendFormula blendFormula; 9305be6c95fa95a518ab109339df4695d6dda6e2419Brian Salomon blendFormula = get_lcd_blend_formula(SkBlendMode::kSrcOver); 931d7b1159d787de27d75032ec213903a03962ec839Greg Daniel // See comment above regarding why the opaque check is commented out here. 932d7b1159d787de27d75032ec213903a03962ec839Greg Daniel if (/*!color.isOpaque() ||*/ 9336ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlendingSupport())) { 934a076d8711d24b8181f894038a4fd34d5327f1717Brian Salomon return sk_sp<GrXferProcessor>( 9356ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel new ShaderPDXferProcessor(hasMixedSamples, SkBlendMode::kSrcOver, coverage)); 936c4b72720e75313079212e69e46a5ef7c474b2305egdaniel } 9376ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel return sk_sp<GrXferProcessor>(new PorterDuffXferProcessor(blendFormula, coverage)); 938c4b72720e75313079212e69e46a5ef7c474b2305egdaniel} 939c4b72720e75313079212e69e46a5ef7c474b2305egdaniel 940d61c9d93b126dca0af17eff89be8536944dadf81Brian Salomonsk_sp<const GrXferProcessor> GrPorterDuffXPFactory::MakeNoCoverageXP(SkBlendMode blendmode) { 941119fb2b9505aea87900d2cf5cf3573814bcae08ccsmartdalton BlendFormula formula = get_blend_formula(false, false, false, blendmode); 9426ebe4b9dbeab68ca3b6da61fd08f22cdc080267dGreg Daniel return sk_make_sp<PorterDuffXferProcessor>(formula, GrProcessorAnalysisCoverage::kNone); 943119fb2b9505aea87900d2cf5cf3573814bcae08ccsmartdalton} 944119fb2b9505aea87900d2cf5cf3573814bcae08ccsmartdalton 945318538484f99253b6a2acf97d4d1b420e628b289Brian SalomonGrXPFactory::AnalysisProperties GrPorterDuffXPFactory::SrcOverAnalysisProperties( 946a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon const GrProcessorAnalysisColor& color, 947a811b1200cc0b5e3819c89f62def23ec203d4b5aBrian Salomon const GrProcessorAnalysisCoverage& coverage, 9489a725dd9485654155e2e4196c32d372360bcdb61Brian Osman const GrCaps& caps, 9499a725dd9485654155e2e4196c32d372360bcdb61Brian Osman GrPixelConfigIsClamped dstIsClamped) { 9509a725dd9485654155e2e4196c32d372360bcdb61Brian Osman return analysis_properties(color, coverage, caps, dstIsClamped, SkBlendMode::kSrcOver); 951c4b72720e75313079212e69e46a5ef7c474b2305egdaniel} 952