Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: src/gpu/effects/GrPorterDuffXferProcessor.cpp

Issue 808813002: Add Coverage Drawing XP (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: more nits Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/effects/GrCoverageSetOpXP.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "effects/GrPorterDuffXferProcessor.h" 8 #include "effects/GrPorterDuffXferProcessor.h"
9 9
10 #include "GrBlend.h" 10 #include "GrBlend.h"
11 #include "GrDrawState.h"
12 #include "GrDrawTargetCaps.h" 11 #include "GrDrawTargetCaps.h"
13 #include "GrInvariantOutput.h" 12 #include "GrInvariantOutput.h"
14 #include "GrProcessor.h" 13 #include "GrProcessor.h"
14 #include "GrProcOptInfo.h"
15 #include "GrTypes.h" 15 #include "GrTypes.h"
16 #include "GrXferProcessor.h" 16 #include "GrXferProcessor.h"
17 #include "gl/GrGLXferProcessor.h" 17 #include "gl/GrGLXferProcessor.h"
18 #include "gl/builders/GrGLFragmentShaderBuilder.h" 18 #include "gl/builders/GrGLFragmentShaderBuilder.h"
19 #include "gl/builders/GrGLProgramBuilder.h" 19 #include "gl/builders/GrGLProgramBuilder.h"
20 20
21 static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff, bool isCoverageD rawing) { 21 static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff) {
22 /* 22 /*
23 The fractional coverage is f. 23 The fractional coverage is f.
24 The src and dst coeffs are Cs and Cd. 24 The src and dst coeffs are Cs and Cd.
25 The dst and src colors are S and D. 25 The dst and src colors are S and D.
26 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou rce color's alpha 26 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou rce color's alpha
27 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second 27 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
28 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss ibilities for Cd we 28 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss ibilities for Cd we
29 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D. 29 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
30 Also, if we're directly rendering coverage (isCoverageDrawing) then coverag e is treated as
31 color by definition.
32 */ 30 */
33 // TODO: Once we have a CoverageDrawing XP, we don't need to check is Covera geDrawing here
34 return kOne_GrBlendCoeff == dstCoeff || 31 return kOne_GrBlendCoeff == dstCoeff ||
35 kISA_GrBlendCoeff == dstCoeff || 32 kISA_GrBlendCoeff == dstCoeff ||
36 kISC_GrBlendCoeff == dstCoeff || 33 kISC_GrBlendCoeff == dstCoeff;
37 isCoverageDrawing;
38 } 34 }
39 35
40 class GrGLPorterDuffXferProcessor : public GrGLXferProcessor { 36 class GrGLPorterDuffXferProcessor : public GrGLXferProcessor {
41 public: 37 public:
42 GrGLPorterDuffXferProcessor(const GrProcessor&) {} 38 GrGLPorterDuffXferProcessor(const GrProcessor&) {}
43 39
44 virtual ~GrGLPorterDuffXferProcessor() {} 40 virtual ~GrGLPorterDuffXferProcessor() {}
45 41
46 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE { 42 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
47 const GrPorterDuffXferProcessor& xp = args.fXP.cast<GrPorterDuffXferProc essor>(); 43 const GrPorterDuffXferProcessor& xp = args.fXP.cast<GrPorterDuffXferProc essor>();
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 117
122 void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps, 118 void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps,
123 GrProcessorKeyBuilder* b) cons t { 119 GrProcessorKeyBuilder* b) cons t {
124 GrGLPorterDuffXferProcessor::GenKey(*this, caps, b); 120 GrGLPorterDuffXferProcessor::GenKey(*this, caps, b);
125 } 121 }
126 122
127 GrGLXferProcessor* GrPorterDuffXferProcessor::createGLInstance() const { 123 GrGLXferProcessor* GrPorterDuffXferProcessor::createGLInstance() const {
128 return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this)); 124 return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this));
129 } 125 }
130 126
131 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou t) const {
132 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
133 }
134
135 GrXferProcessor::OptFlags 127 GrXferProcessor::OptFlags
136 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, 128 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
137 const GrProcOptInfo& coveragePOI, 129 const GrProcOptInfo& coveragePOI,
138 bool isCoverageDrawing,
139 bool colorWriteDisabled, 130 bool colorWriteDisabled,
140 bool doesStencilWrite, 131 bool doesStencilWrite,
141 GrColor* overrideColor, 132 GrColor* overrideColor,
142 const GrDrawTargetCaps& caps) { 133 const GrDrawTargetCaps& caps) {
143 GrXferProcessor::OptFlags optFlags; 134 GrXferProcessor::OptFlags optFlags;
144 // Optimizations when doing RGB Coverage 135 // Optimizations when doing RGB Coverage
145 if (coveragePOI.isFourChannelOutput()) { 136 if (coveragePOI.isFourChannelOutput()) {
146 // We want to force our primary output to be alpha * Coverage, where alp ha is the alpha 137 // We want to force our primary output to be alpha * Coverage, where alp ha is the alpha
147 // value of the blend the constant. We should already have valid blend c oeff's if we are at 138 // value of the blend the constant. We should already have valid blend c oeff's if we are at
148 // a point where we have RGB coverage. We don't need any color stages si nce the known color 139 // a point where we have RGB coverage. We don't need any color stages si nce the known color
149 // output is already baked into the blendConstant. 140 // output is already baked into the blendConstant.
150 uint8_t alpha = GrColorUnpackA(fBlendConstant); 141 uint8_t alpha = GrColorUnpackA(fBlendConstant);
151 *overrideColor = GrColorPackRGBA(alpha, alpha, alpha, alpha); 142 *overrideColor = GrColorPackRGBA(alpha, alpha, alpha, alpha);
152 optFlags = GrXferProcessor::kOverrideColor_OptFlag; 143 optFlags = GrXferProcessor::kOverrideColor_OptFlag;
153 } else { 144 } else {
154 optFlags = this->internalGetOptimizations(colorPOI, 145 optFlags = this->internalGetOptimizations(colorPOI,
155 coveragePOI, 146 coveragePOI,
156 isCoverageDrawing,
157 colorWriteDisabled, 147 colorWriteDisabled,
158 doesStencilWrite); 148 doesStencilWrite);
159 } 149 }
160 this->calcOutputTypes(optFlags, caps, isCoverageDrawing || coveragePOI.isSol idWhite(), 150 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite(),
161 colorPOI.readsDst() || coveragePOI.readsDst()); 151 colorPOI.readsDst() || coveragePOI.readsDst());
162 return optFlags; 152 return optFlags;
163 } 153 }
164 154
165 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla gs, 155 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla gs,
166 const GrDrawTargetCaps& caps, 156 const GrDrawTargetCaps& caps,
167 bool hasSolidCoverage, bool read sDst) { 157 bool hasSolidCoverage, bool read sDst) {
168 if (optFlags & kIgnoreColor_OptFlag) { 158 if (optFlags & kIgnoreColor_OptFlag) {
169 if (optFlags & kIgnoreCoverage_OptFlag) { 159 if (optFlags & kIgnoreCoverage_OptFlag) {
170 fPrimaryOutputType = kNone_PrimaryOutputType; 160 fPrimaryOutputType = kNone_PrimaryOutputType;
(...skipping 30 matching lines...) Expand all
201 kOne_GrBlendCoeff == fSrcBlend && 191 kOne_GrBlendCoeff == fSrcBlend &&
202 kZero_GrBlendCoeff == fDstBlend) { 192 kZero_GrBlendCoeff == fDstBlend) {
203 fPrimaryOutputType = kCombineWithDst_PrimaryOutputType; 193 fPrimaryOutputType = kCombineWithDst_PrimaryOutputType;
204 } 194 }
205 } 195 }
206 } 196 }
207 197
208 GrXferProcessor::OptFlags 198 GrXferProcessor::OptFlags
209 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO I, 199 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO I,
210 const GrProcOptInfo& coverag ePOI, 200 const GrProcOptInfo& coverag ePOI,
211 bool isCoverageDrawing,
212 bool colorWriteDisabled, 201 bool colorWriteDisabled,
213 bool doesStencilWrite) { 202 bool doesStencilWrite) {
214 if (colorWriteDisabled) { 203 if (colorWriteDisabled) {
215 fSrcBlend = kZero_GrBlendCoeff; 204 fSrcBlend = kZero_GrBlendCoeff;
216 fDstBlend = kOne_GrBlendCoeff; 205 fDstBlend = kOne_GrBlendCoeff;
217 } 206 }
218 207
219 bool srcAIsOne; 208 bool srcAIsOne;
220 bool hasCoverage; 209 bool hasCoverage;
221 if (isCoverageDrawing) { 210
222 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque(); 211 srcAIsOne = colorPOI.isOpaque();
223 hasCoverage = false; 212 hasCoverage = !coveragePOI.isSolidWhite();
224 } else {
225 srcAIsOne = colorPOI.isOpaque();
226 hasCoverage = !coveragePOI.isSolidWhite();
227 }
228 213
229 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || 214 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend ||
230 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); 215 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne);
231 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || 216 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend ||
232 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); 217 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne);
233 218
234 // When coeffs are (0,1) there is no reason to draw at all, unless 219 // When coeffs are (0,1) there is no reason to draw at all, unless
235 // stenciling is enabled. Having color writes disabled is effectively 220 // stenciling is enabled. Having color writes disabled is effectively
236 // (0,1). 221 // (0,1).
237 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { 222 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) {
(...skipping 17 matching lines...) Expand all
255 return GrXferProcessor::kNone_Opt; 240 return GrXferProcessor::kNone_Opt;
256 } else if (kZero_GrBlendCoeff == fSrcBlend) { 241 } else if (kZero_GrBlendCoeff == fSrcBlend) {
257 // if the op is "clear" then we don't need to emit a color 242 // if the op is "clear" then we don't need to emit a color
258 // or blend, just write transparent black into the dst. 243 // or blend, just write transparent black into the dst.
259 fSrcBlend = kOne_GrBlendCoeff; 244 fSrcBlend = kOne_GrBlendCoeff;
260 fDstBlend = kZero_GrBlendCoeff; 245 fDstBlend = kZero_GrBlendCoeff;
261 return GrXferProcessor::kIgnoreColor_OptFlag | 246 return GrXferProcessor::kIgnoreColor_OptFlag |
262 GrXferProcessor::kIgnoreCoverage_OptFlag; 247 GrXferProcessor::kIgnoreCoverage_OptFlag;
263 } 248 }
264 } 249 }
265 } else if (isCoverageDrawing) { 250 } else {
266 // we have coverage but we aren't distinguishing it from alpha by reques t.
267 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
268 } else {
269 // check whether coverage can be safely rolled into alpha 251 // check whether coverage can be safely rolled into alpha
270 // of if we can skip color computation and just emit coverage 252 // of if we can skip color computation and just emit coverage
271 if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) { 253 if (can_tweak_alpha_for_coverage(fDstBlend)) {
272 return GrXferProcessor::kSetCoverageDrawing_OptFlag; 254 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
273 } 255 }
274 if (dstCoeffIsZero) { 256 if (dstCoeffIsZero) {
275 if (kZero_GrBlendCoeff == fSrcBlend) { 257 if (kZero_GrBlendCoeff == fSrcBlend) {
276 // the source color is not included in the blend 258 // the source color is not included in the blend
277 // the dst coeff is effectively zero so blend works out to: 259 // the dst coeff is effectively zero so blend works out to:
278 // (c)(0)D + (1-c)D = (1-c)D. 260 // (c)(0)D + (1-c)D = (1-c)D.
279 fDstBlend = kISA_GrBlendCoeff; 261 fDstBlend = kISA_GrBlendCoeff;
280 return GrXferProcessor::kIgnoreColor_OptFlag | 262 return GrXferProcessor::kIgnoreColor_OptFlag |
281 GrXferProcessor::kSetCoverageDrawing_OptFlag; 263 GrXferProcessor::kSetCoverageDrawing_OptFlag;
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 uint32_t knownColorFlags) const { 393 uint32_t knownColorFlags) const {
412 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && 394 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff &&
413 kRGBA_GrColorComponentFlags == knownColorFlags) { 395 kRGBA_GrColorComponentFlags == knownColorFlags) {
414 return true; 396 return true;
415 } 397 }
416 return false; 398 return false;
417 } 399 }
418 400
419 bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI, 401 bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI,
420 const GrProcOptInfo& coveragePOI, 402 const GrProcOptInfo& coveragePOI,
421 bool isCoverageDrawing,
422 bool colorWriteDisabled) const { 403 bool colorWriteDisabled) const {
423 bool srcAIsOne = colorPOI.isOpaque() && (!isCoverageDrawing || coveragePOI.i sOpaque()); 404 bool srcAIsOne = colorPOI.isOpaque();
424 405
425 if (colorWriteDisabled) { 406 if (colorWriteDisabled) {
426 return true; 407 return true;
427 } 408 }
428 409
429 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstCoeff || 410 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstCoeff ||
430 (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne); 411 (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne);
431 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstCoeff || 412 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstCoeff ||
432 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne); 413 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne);
433 414
434 if ((kZero_GrBlendCoeff == fSrcCoeff && dstCoeffIsOne)) { 415 if ((kZero_GrBlendCoeff == fSrcCoeff && dstCoeffIsOne)) {
435 return true; 416 return true;
436 } 417 }
437 418
438 // if we don't have coverage we can check whether the dst 419 // if we don't have coverage we can check whether the dst
439 // has to read at all. 420 // has to read at all.
440 if (isCoverageDrawing) { 421 // check whether coverage can be safely rolled into alpha
441 // we have coverage but we aren't distinguishing it from alpha by reques t. 422 // of if we can skip color computation and just emit coverage
423 if (this->canTweakAlphaForCoverage()) {
442 return true; 424 return true;
443 } else { 425 }
444 // check whether coverage can be safely rolled into alpha 426 if (dstCoeffIsZero) {
445 // of if we can skip color computation and just emit coverage 427 if (kZero_GrBlendCoeff == fSrcCoeff) {
446 if (this->canTweakAlphaForCoverage(isCoverageDrawing)) {
447 return true; 428 return true;
429 } else if (srcAIsOne) {
430 return true;
448 } 431 }
449 if (dstCoeffIsZero) { 432 } else if (dstCoeffIsOne) {
450 if (kZero_GrBlendCoeff == fSrcCoeff) { 433 return true;
451 return true;
452 } else if (srcAIsOne) {
453 return true;
454 }
455 } else if (dstCoeffIsOne) {
456 return true;
457 }
458 } 434 }
459 435
460 // TODO: once all SkXferEffects are XP's then we will never reads dst here s ince only XP's 436 // TODO: once all SkXferEffects are XP's then we will never reads dst here s ince only XP's
461 // will readDst and PD XP's don't read dst. 437 // will readDst and PD XP's don't read dst.
462 if ((colorPOI.readsDst() || coveragePOI.readsDst()) && 438 if ((colorPOI.readsDst() || coveragePOI.readsDst()) &&
463 kOne_GrBlendCoeff == fSrcCoeff && kZero_GrBlendCoeff == fDstCoeff) { 439 kOne_GrBlendCoeff == fSrcCoeff && kZero_GrBlendCoeff == fDstCoeff) {
464 return true; 440 return true;
465 } 441 }
466 442
467 return false; 443 return false;
468 } 444 }
469 445
470 bool GrPorterDuffXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI, 446 bool GrPorterDuffXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI,
471 const GrProcOptInfo& coveragePOI, 447 const GrProcOptInfo& coveragePOI,
472 bool isCoverageDrawing,
473 bool colorWriteDisabled) const { 448 bool colorWriteDisabled) const {
474 if (!(isCoverageDrawing || coveragePOI.isSolidWhite())) { 449 if (!coveragePOI.isSolidWhite()) {
475 return true; 450 return true;
476 } 451 }
477 452
478 // TODO: once all SkXferEffects are XP's then we will never reads dst here s ince only XP's 453 // TODO: once all SkXferEffects are XP's then we will never reads dst here s ince only XP's
479 // will readDst and PD XP's don't read dst. 454 // will readDst and PD XP's don't read dst.
480 if ((!colorWriteDisabled && colorPOI.readsDst()) || coveragePOI.readsDst()) { 455 if ((!colorWriteDisabled && colorPOI.readsDst()) || coveragePOI.readsDst()) {
481 return true; 456 return true;
482 } 457 }
483 458
484 if (GrBlendCoeffRefsDst(fSrcCoeff)) { 459 if (GrBlendCoeffRefsDst(fSrcCoeff)) {
485 return true; 460 return true;
486 } 461 }
487 462
488 bool srcAIsOne = colorPOI.isOpaque() && (!isCoverageDrawing || coveragePOI.i sOpaque()); 463 bool srcAIsOne = colorPOI.isOpaque();
489 464
490 if (!(kZero_GrBlendCoeff == fDstCoeff || 465 if (!(kZero_GrBlendCoeff == fDstCoeff ||
491 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne))) { 466 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne))) {
492 return true; 467 return true;
493 } 468 }
494 469
495 return false; 470 return false;
496 } 471 }
497 472
498 bool GrPorterDuffXPFactory::canTweakAlphaForCoverage(bool isCoverageDrawing) con st { 473 bool GrPorterDuffXPFactory::canTweakAlphaForCoverage() const {
499 return can_tweak_alpha_for_coverage(fDstCoeff, isCoverageDrawing); 474 return can_tweak_alpha_for_coverage(fDstCoeff);
500 } 475 }
501 476
502 bool GrPorterDuffXPFactory::getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI , 477 bool GrPorterDuffXPFactory::getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI ,
503 const GrProcOptInfo& coverage POI, 478 const GrProcOptInfo& coverage POI,
504 GrColor* solidColor, 479 GrColor* solidColor,
505 uint32_t* solidColorKnownComp onents) const { 480 uint32_t* solidColorKnownComp onents) const {
506 if (!coveragePOI.isSolidWhite()) { 481 if (!coveragePOI.isSolidWhite()) {
507 return false; 482 return false;
508 } 483 }
509 484
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 } while (GrBlendCoeffRefsSrc(src)); 547 } while (GrBlendCoeffRefsSrc(src));
573 548
574 GrBlendCoeff dst; 549 GrBlendCoeff dst;
575 do { 550 do {
576 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff)); 551 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff));
577 } while (GrBlendCoeffRefsDst(dst)); 552 } while (GrBlendCoeffRefsDst(dst));
578 553
579 return GrPorterDuffXPFactory::Create(src, dst); 554 return GrPorterDuffXPFactory::Create(src, dst);
580 } 555 }
581 556
OLDNEW
« no previous file with comments | « src/gpu/effects/GrCoverageSetOpXP.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698