GrGLSLBlend.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /*
  2. * Copyright 2015 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/core/SkBlendModePriv.h"
  8. #include "src/gpu/glsl/GrGLSLBlend.h"
  9. #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
  10. #include "src/gpu/glsl/GrGLSLProgramBuilder.h"
  11. //////////////////////////////////////////////////////////////////////////////
  12. // Advanced (non-coeff) blend helpers
  13. //////////////////////////////////////////////////////////////////////////////
  14. static void hard_light(GrGLSLFragmentBuilder* fsBuilder,
  15. const char* final,
  16. const char* src,
  17. const char* dst) {
  18. static const char kComponents[] = { 'r', 'g', 'b' };
  19. for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
  20. char component = kComponents[i];
  21. fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src);
  22. fsBuilder->codeAppendf("%s.%c = 2.0 * %s.%c * %s.%c;",
  23. final, component, src, component, dst, component);
  24. fsBuilder->codeAppend("} else {");
  25. fsBuilder->codeAppendf("%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);",
  26. final, component, src, dst, dst, dst, component, src, src,
  27. component);
  28. fsBuilder->codeAppend("}");
  29. }
  30. fsBuilder->codeAppendf("%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);",
  31. final, src, dst, dst, src);
  32. }
  33. // Does one component of color-dodge
  34. static void color_dodge_component(GrGLSLFragmentBuilder* fsBuilder,
  35. const char* final,
  36. const char* src,
  37. const char* dst,
  38. const char component) {
  39. const char* divisorGuard = "";
  40. const GrShaderCaps* shaderCaps = fsBuilder->getProgramBuilder()->shaderCaps();
  41. if (shaderCaps->mustGuardDivisionEvenAfterExplicitZeroCheck()) {
  42. divisorGuard = "+ 0.00000001";
  43. }
  44. fsBuilder->codeAppendf("if (0.0 == %s.%c) {", dst, component);
  45. fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
  46. final, component, src, component, dst);
  47. fsBuilder->codeAppend("} else {");
  48. fsBuilder->codeAppendf("half d = %s.a - %s.%c;", src, src, component);
  49. fsBuilder->codeAppend("if (0.0 == d) {");
  50. fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
  51. final, component, src, dst, src, component, dst, dst, component,
  52. src);
  53. fsBuilder->codeAppend("} else {");
  54. fsBuilder->codeAppendf("d = min(%s.a, %s.%c * %s.a / (d %s));",
  55. dst, dst, component, src, divisorGuard);
  56. fsBuilder->codeAppendf("%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
  57. final, component, src, src, component, dst, dst, component, src);
  58. fsBuilder->codeAppend("}");
  59. fsBuilder->codeAppend("}");
  60. }
  61. // Does one component of color-burn
  62. static void color_burn_component(GrGLSLFragmentBuilder* fsBuilder,
  63. const char* final,
  64. const char* src,
  65. const char* dst,
  66. const char component) {
  67. const char* divisorGuard = "";
  68. const GrShaderCaps* shaderCaps = fsBuilder->getProgramBuilder()->shaderCaps();
  69. if (shaderCaps->mustGuardDivisionEvenAfterExplicitZeroCheck()) {
  70. divisorGuard = "+ 0.00000001";
  71. }
  72. fsBuilder->codeAppendf("if (%s.a == %s.%c) {", dst, dst, component);
  73. fsBuilder->codeAppendf("%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
  74. final, component, src, dst, src, component, dst, dst, component,
  75. src);
  76. fsBuilder->codeAppendf("} else if (0.0 == %s.%c) {", src, component);
  77. fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
  78. final, component, dst, component, src);
  79. fsBuilder->codeAppend("} else {");
  80. fsBuilder->codeAppendf("half d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / (%s.%c %s));",
  81. dst, dst, dst, component, src, src, component, divisorGuard);
  82. fsBuilder->codeAppendf("%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
  83. final, component, src, src, component, dst, dst, component, src);
  84. fsBuilder->codeAppend("}");
  85. }
  86. // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
  87. static void soft_light_component_pos_dst_alpha(GrGLSLFragmentBuilder* fsBuilder,
  88. const char* final,
  89. const char* src,
  90. const char* dst,
  91. const char component) {
  92. const char* divisorGuard = "";
  93. const GrShaderCaps* shaderCaps = fsBuilder->getProgramBuilder()->shaderCaps();
  94. if (shaderCaps->mustGuardDivisionEvenAfterExplicitZeroCheck()) {
  95. divisorGuard = "+ 0.00000001";
  96. }
  97. // if (2S < Sa)
  98. fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src);
  99. // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
  100. fsBuilder->codeAppendf("%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / (%s.a %s) +"
  101. "(1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);",
  102. final, component, dst, component, dst, component, src, src,
  103. component, dst, divisorGuard, dst, src, component, dst, component, src,
  104. src, component);
  105. // else if (4D < Da)
  106. fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {",
  107. dst, component, dst);
  108. fsBuilder->codeAppendf("half DSqd = %s.%c * %s.%c;",
  109. dst, component, dst, component);
  110. fsBuilder->codeAppendf("half DCub = DSqd * %s.%c;", dst, component);
  111. fsBuilder->codeAppendf("half DaSqd = %s.a * %s.a;", dst, dst);
  112. fsBuilder->codeAppendf("half DaCub = DaSqd * %s.a;", dst);
  113. // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da^2
  114. fsBuilder->codeAppendf("%s.%c ="
  115. "(DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) +"
  116. " 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c) -"
  117. " DaCub*%s.%c) / (DaSqd %s);",
  118. final, component, src, component, dst, component,
  119. src, src, component, dst, src, src, component, src, src,
  120. component, src, component, divisorGuard);
  121. fsBuilder->codeAppendf("} else {");
  122. // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
  123. fsBuilder->codeAppendf("%s.%c = %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c -"
  124. " sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c;",
  125. final, component, dst, component, src, src, component, src, component,
  126. dst, dst, component, src, src, component, dst, src, component);
  127. fsBuilder->codeAppendf("}");
  128. }
  129. // Adds a function that takes two colors and an alpha as input. It produces a color with the
  130. // hue and saturation of the first color, the luminosity of the second color, and the input
  131. // alpha. It has this signature:
  132. // float3 set_luminance(float3 hueSatColor, float alpha, float3 lumColor).
  133. static void add_lum_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setLumFunction) {
  134. // Emit a helper that gets the luminance of a color.
  135. SkString getFunction;
  136. GrShaderVar getLumArgs[] = {
  137. GrShaderVar("color", kHalf3_GrSLType),
  138. };
  139. SkString getLumBody("return dot(half3(0.3, 0.59, 0.11), color);");
  140. fsBuilder->emitFunction(kHalf_GrSLType,
  141. "luminance",
  142. SK_ARRAY_COUNT(getLumArgs), getLumArgs,
  143. getLumBody.c_str(),
  144. &getFunction);
  145. // Emit the set luminance function.
  146. GrShaderVar setLumArgs[] = {
  147. GrShaderVar("hueSat", kHalf3_GrSLType),
  148. GrShaderVar("alpha", kHalf_GrSLType),
  149. GrShaderVar("lumColor", kHalf3_GrSLType),
  150. };
  151. SkString setLumBody;
  152. setLumBody.printf("half diff = %s(lumColor - hueSat);", getFunction.c_str());
  153. setLumBody.append("half3 outColor = hueSat + diff;");
  154. setLumBody.appendf("half outLum = %s(outColor);", getFunction.c_str());
  155. setLumBody.append("half minComp = min(min(outColor.r, outColor.g), outColor.b);"
  156. "half maxComp = max(max(outColor.r, outColor.g), outColor.b);"
  157. "if (minComp < 0.0 && outLum != minComp) {"
  158. "outColor = outLum + ((outColor - half3(outLum, outLum, outLum)) * outLum) /"
  159. "(outLum - minComp);"
  160. "}"
  161. "if (maxComp > alpha && maxComp != outLum) {"
  162. "outColor = outLum +"
  163. "((outColor - half3(outLum, outLum, outLum)) * (alpha - outLum)) /"
  164. "(maxComp - outLum);"
  165. "}"
  166. "return outColor;");
  167. fsBuilder->emitFunction(kHalf3_GrSLType,
  168. "set_luminance",
  169. SK_ARRAY_COUNT(setLumArgs), setLumArgs,
  170. setLumBody.c_str(),
  171. setLumFunction);
  172. }
  173. // Adds a function that creates a color with the hue and luminosity of one input color and
  174. // the saturation of another color. It will have this signature:
  175. // float set_saturation(float3 hueLumColor, float3 satColor)
  176. static void add_sat_function(GrGLSLFragmentBuilder* fsBuilder, SkString* setSatFunction) {
  177. // Emit a helper that gets the saturation of a color
  178. SkString getFunction;
  179. GrShaderVar getSatArgs[] = { GrShaderVar("color", kHalf3_GrSLType) };
  180. SkString getSatBody;
  181. getSatBody.printf("return max(max(color.r, color.g), color.b) - "
  182. "min(min(color.r, color.g), color.b);");
  183. fsBuilder->emitFunction(kHalf_GrSLType,
  184. "saturation",
  185. SK_ARRAY_COUNT(getSatArgs), getSatArgs,
  186. getSatBody.c_str(),
  187. &getFunction);
  188. // Emit a helper that sets the saturation given sorted input channels. This used
  189. // to use inout params for min, mid, and max components but that seems to cause
  190. // problems on PowerVR drivers. So instead it returns a float3 where r, g ,b are the
  191. // adjusted min, mid, and max inputs, respectively.
  192. SkString helperFunction;
  193. GrShaderVar helperArgs[] = {
  194. GrShaderVar("minComp", kHalf_GrSLType),
  195. GrShaderVar("midComp", kHalf_GrSLType),
  196. GrShaderVar("maxComp", kHalf_GrSLType),
  197. GrShaderVar("sat", kHalf_GrSLType),
  198. };
  199. static const char kHelperBody[] = "if (minComp < maxComp) {"
  200. "half3 result;"
  201. "result.r = 0.0;"
  202. "result.g = sat * (midComp - minComp) / (maxComp - minComp);"
  203. "result.b = sat;"
  204. "return result;"
  205. "} else {"
  206. "return half3(0, 0, 0);"
  207. "}";
  208. fsBuilder->emitFunction(kHalf3_GrSLType,
  209. "set_saturation_helper",
  210. SK_ARRAY_COUNT(helperArgs), helperArgs,
  211. kHelperBody,
  212. &helperFunction);
  213. GrShaderVar setSatArgs[] = {
  214. GrShaderVar("hueLumColor", kHalf3_GrSLType),
  215. GrShaderVar("satColor", kHalf3_GrSLType),
  216. };
  217. const char* helpFunc = helperFunction.c_str();
  218. SkString setSatBody;
  219. setSatBody.appendf("half sat = %s(satColor);"
  220. "if (hueLumColor.r <= hueLumColor.g) {"
  221. "if (hueLumColor.g <= hueLumColor.b) {"
  222. "hueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);"
  223. "} else if (hueLumColor.r <= hueLumColor.b) {"
  224. "hueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);"
  225. "} else {"
  226. "hueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);"
  227. "}"
  228. "} else if (hueLumColor.r <= hueLumColor.b) {"
  229. "hueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);"
  230. "} else if (hueLumColor.g <= hueLumColor.b) {"
  231. "hueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);"
  232. "} else {"
  233. "hueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);"
  234. "}"
  235. "return hueLumColor;",
  236. getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
  237. helpFunc, helpFunc);
  238. fsBuilder->emitFunction(kHalf3_GrSLType,
  239. "set_saturation",
  240. SK_ARRAY_COUNT(setSatArgs), setSatArgs,
  241. setSatBody.c_str(),
  242. setSatFunction);
  243. }
  244. static void emit_advanced_xfermode_code(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
  245. const char* dstColor, const char* outputColor,
  246. SkBlendMode mode) {
  247. SkASSERT(srcColor);
  248. SkASSERT(dstColor);
  249. SkASSERT(outputColor);
  250. // These all perform src-over on the alpha channel.
  251. fsBuilder->codeAppendf("%s.a = %s.a + (1.0 - %s.a) * %s.a;",
  252. outputColor, srcColor, srcColor, dstColor);
  253. switch (mode) {
  254. case SkBlendMode::kOverlay:
  255. // Overlay is Hard-Light with the src and dst reversed
  256. hard_light(fsBuilder, outputColor, dstColor, srcColor);
  257. break;
  258. case SkBlendMode::kDarken:
  259. fsBuilder->codeAppendf("%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
  260. "(1.0 - %s.a) * %s.rgb + %s.rgb);",
  261. outputColor,
  262. srcColor, dstColor, srcColor,
  263. dstColor, srcColor, dstColor);
  264. break;
  265. case SkBlendMode::kLighten:
  266. fsBuilder->codeAppendf("%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
  267. "(1.0 - %s.a) * %s.rgb + %s.rgb);",
  268. outputColor,
  269. srcColor, dstColor, srcColor,
  270. dstColor, srcColor, dstColor);
  271. break;
  272. case SkBlendMode::kColorDodge:
  273. color_dodge_component(fsBuilder, outputColor, srcColor, dstColor, 'r');
  274. color_dodge_component(fsBuilder, outputColor, srcColor, dstColor, 'g');
  275. color_dodge_component(fsBuilder, outputColor, srcColor, dstColor, 'b');
  276. break;
  277. case SkBlendMode::kColorBurn:
  278. color_burn_component(fsBuilder, outputColor, srcColor, dstColor, 'r');
  279. color_burn_component(fsBuilder, outputColor, srcColor, dstColor, 'g');
  280. color_burn_component(fsBuilder, outputColor, srcColor, dstColor, 'b');
  281. break;
  282. case SkBlendMode::kHardLight:
  283. hard_light(fsBuilder, outputColor, srcColor, dstColor);
  284. break;
  285. case SkBlendMode::kSoftLight:
  286. fsBuilder->codeAppendf("if (0.0 == %s.a) {", dstColor);
  287. fsBuilder->codeAppendf("%s.rgba = %s;", outputColor, srcColor);
  288. fsBuilder->codeAppendf("} else {");
  289. soft_light_component_pos_dst_alpha(fsBuilder, outputColor, srcColor, dstColor, 'r');
  290. soft_light_component_pos_dst_alpha(fsBuilder, outputColor, srcColor, dstColor, 'g');
  291. soft_light_component_pos_dst_alpha(fsBuilder, outputColor, srcColor, dstColor, 'b');
  292. fsBuilder->codeAppendf("}");
  293. break;
  294. case SkBlendMode::kDifference:
  295. fsBuilder->codeAppendf("%s.rgb = %s.rgb + %s.rgb -"
  296. "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);",
  297. outputColor, srcColor, dstColor, srcColor, dstColor,
  298. dstColor, srcColor);
  299. break;
  300. case SkBlendMode::kExclusion:
  301. fsBuilder->codeAppendf("%s.rgb = %s.rgb + %s.rgb - "
  302. "2.0 * %s.rgb * %s.rgb;",
  303. outputColor, dstColor, srcColor, dstColor, srcColor);
  304. break;
  305. case SkBlendMode::kMultiply:
  306. fsBuilder->codeAppendf("%s.rgb = (1.0 - %s.a) * %s.rgb + "
  307. "(1.0 - %s.a) * %s.rgb + "
  308. "%s.rgb * %s.rgb;",
  309. outputColor, srcColor, dstColor, dstColor, srcColor,
  310. srcColor, dstColor);
  311. break;
  312. case SkBlendMode::kHue: {
  313. // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
  314. SkString setSat, setLum;
  315. add_sat_function(fsBuilder, &setSat);
  316. add_lum_function(fsBuilder, &setLum);
  317. fsBuilder->codeAppendf("half4 dstSrcAlpha = %s * %s.a;",
  318. dstColor, srcColor);
  319. fsBuilder->codeAppendf("%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb),"
  320. "dstSrcAlpha.a, dstSrcAlpha.rgb);",
  321. outputColor, setLum.c_str(), setSat.c_str(), srcColor,
  322. dstColor);
  323. fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;",
  324. outputColor, srcColor, dstColor, dstColor, srcColor);
  325. break;
  326. }
  327. case SkBlendMode::kSaturation: {
  328. // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
  329. SkString setSat, setLum;
  330. add_sat_function(fsBuilder, &setSat);
  331. add_lum_function(fsBuilder, &setLum);
  332. fsBuilder->codeAppendf("half4 dstSrcAlpha = %s * %s.a;",
  333. dstColor, srcColor);
  334. fsBuilder->codeAppendf("%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a),"
  335. "dstSrcAlpha.a, dstSrcAlpha.rgb);",
  336. outputColor, setLum.c_str(), setSat.c_str(), srcColor,
  337. dstColor);
  338. fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;",
  339. outputColor, srcColor, dstColor, dstColor, srcColor);
  340. break;
  341. }
  342. case SkBlendMode::kColor: {
  343. // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
  344. SkString setLum;
  345. add_lum_function(fsBuilder, &setLum);
  346. fsBuilder->codeAppendf("half4 srcDstAlpha = %s * %s.a;",
  347. srcColor, dstColor);
  348. fsBuilder->codeAppendf("%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);",
  349. outputColor, setLum.c_str(), dstColor, srcColor);
  350. fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;",
  351. outputColor, srcColor, dstColor, dstColor, srcColor);
  352. break;
  353. }
  354. case SkBlendMode::kLuminosity: {
  355. // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
  356. SkString setLum;
  357. add_lum_function(fsBuilder, &setLum);
  358. fsBuilder->codeAppendf("half4 srcDstAlpha = %s * %s.a;",
  359. srcColor, dstColor);
  360. fsBuilder->codeAppendf("%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);",
  361. outputColor, setLum.c_str(), dstColor, srcColor);
  362. fsBuilder->codeAppendf("%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;",
  363. outputColor, srcColor, dstColor, dstColor, srcColor);
  364. break;
  365. }
  366. default:
  367. SK_ABORT("Unknown Custom Xfer mode.");
  368. break;
  369. }
  370. }
  371. //////////////////////////////////////////////////////////////////////////////
  372. // Porter-Duff blend helper
  373. //////////////////////////////////////////////////////////////////////////////
  374. static bool append_porterduff_term(GrGLSLFragmentBuilder* fsBuilder, SkBlendModeCoeff coeff,
  375. const char* colorName, const char* srcColorName,
  376. const char* dstColorName, bool hasPrevious) {
  377. if (SkBlendModeCoeff::kZero == coeff) {
  378. return hasPrevious;
  379. } else {
  380. if (hasPrevious) {
  381. fsBuilder->codeAppend(" + ");
  382. }
  383. fsBuilder->codeAppendf("%s", colorName);
  384. switch (coeff) {
  385. case SkBlendModeCoeff::kOne:
  386. break;
  387. case SkBlendModeCoeff::kSC:
  388. fsBuilder->codeAppendf(" * %s", srcColorName);
  389. break;
  390. case SkBlendModeCoeff::kISC:
  391. fsBuilder->codeAppendf(" * (half4(1.0) - %s)", srcColorName);
  392. break;
  393. case SkBlendModeCoeff::kDC:
  394. fsBuilder->codeAppendf(" * %s", dstColorName);
  395. break;
  396. case SkBlendModeCoeff::kIDC:
  397. fsBuilder->codeAppendf(" * (half4(1.0) - %s)", dstColorName);
  398. break;
  399. case SkBlendModeCoeff::kSA:
  400. fsBuilder->codeAppendf(" * %s.a", srcColorName);
  401. break;
  402. case SkBlendModeCoeff::kISA:
  403. fsBuilder->codeAppendf(" * (1.0 - %s.a)", srcColorName);
  404. break;
  405. case SkBlendModeCoeff::kDA:
  406. fsBuilder->codeAppendf(" * %s.a", dstColorName);
  407. break;
  408. case SkBlendModeCoeff::kIDA:
  409. fsBuilder->codeAppendf(" * (1.0 - %s.a)", dstColorName);
  410. break;
  411. default:
  412. SK_ABORT("Unsupported Blend Coeff");
  413. }
  414. return true;
  415. }
  416. }
  417. //////////////////////////////////////////////////////////////////////////////
  418. void GrGLSLBlend::AppendMode(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
  419. const char* dstColor, const char* outColor,
  420. SkBlendMode mode) {
  421. SkBlendModeCoeff srcCoeff, dstCoeff;
  422. if (SkBlendMode_AsCoeff(mode, &srcCoeff, &dstCoeff)) {
  423. // The only coeff mode that can go out of range is plus.
  424. bool clamp = mode == SkBlendMode::kPlus;
  425. fsBuilder->codeAppendf("%s = ", outColor);
  426. if (clamp) {
  427. fsBuilder->codeAppend("clamp(");
  428. }
  429. // append src blend
  430. bool didAppend = append_porterduff_term(fsBuilder, srcCoeff, srcColor, srcColor, dstColor,
  431. false);
  432. // append dst blend
  433. if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstColor, didAppend)) {
  434. fsBuilder->codeAppend("half4(0, 0, 0, 0)");
  435. }
  436. if (clamp) {
  437. fsBuilder->codeAppend(", 0, 1);");
  438. }
  439. fsBuilder->codeAppend(";");
  440. } else {
  441. emit_advanced_xfermode_code(fsBuilder, srcColor, dstColor, outColor, mode);
  442. }
  443. }
  444. void GrGLSLBlend::AppendRegionOp(GrGLSLFragmentBuilder* fsBuilder, const char* srcColor,
  445. const char* dstColor, const char* outColor,
  446. SkRegion::Op regionOp) {
  447. SkBlendModeCoeff srcCoeff, dstCoeff;
  448. switch (regionOp) {
  449. case SkRegion::kReplace_Op:
  450. srcCoeff = SkBlendModeCoeff::kOne;
  451. dstCoeff = SkBlendModeCoeff::kZero;
  452. break;
  453. case SkRegion::kIntersect_Op:
  454. srcCoeff = SkBlendModeCoeff::kDC;
  455. dstCoeff = SkBlendModeCoeff::kZero;
  456. break;
  457. case SkRegion::kUnion_Op:
  458. srcCoeff = SkBlendModeCoeff::kOne;
  459. dstCoeff = SkBlendModeCoeff::kISC;
  460. break;
  461. case SkRegion::kXOR_Op:
  462. srcCoeff = SkBlendModeCoeff::kIDC;
  463. dstCoeff = SkBlendModeCoeff::kISC;
  464. break;
  465. case SkRegion::kDifference_Op:
  466. srcCoeff = SkBlendModeCoeff::kZero;
  467. dstCoeff = SkBlendModeCoeff::kISC;
  468. break;
  469. case SkRegion::kReverseDifference_Op:
  470. srcCoeff = SkBlendModeCoeff::kIDC;
  471. dstCoeff = SkBlendModeCoeff::kZero;
  472. break;
  473. default:
  474. SK_ABORT("Unsupported Op");
  475. // We should never get here but to make compiler happy
  476. srcCoeff = SkBlendModeCoeff::kZero;
  477. dstCoeff = SkBlendModeCoeff::kZero;
  478. }
  479. fsBuilder->codeAppendf("%s = ", outColor);
  480. // append src blend
  481. bool didAppend = append_porterduff_term(fsBuilder, srcCoeff, srcColor, srcColor, dstColor,
  482. false);
  483. // append dst blend
  484. if(!append_porterduff_term(fsBuilder, dstCoeff, dstColor, srcColor, dstColor, didAppend)) {
  485. fsBuilder->codeAppend("half4(0, 0, 0, 0)");
  486. }
  487. fsBuilder->codeAppend(";");
  488. }