GrPorterDuffXferProcessor.cpp 42 KB

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