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

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

Issue 759713002: Make all blending up to GrOptDrawState be handled by the xp/xp factory. (Closed) Base URL: https://skia.googlesource.com/skia.git@xferFactorySolo
Patch Set: rebase 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/SkGr.cpp ('k') | tests/GLProgramsTest.cpp » ('j') | 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 "GrDrawState.h" 11 #include "GrDrawState.h"
11 #include "GrInvariantOutput.h" 12 #include "GrInvariantOutput.h"
12 #include "GrProcessor.h" 13 #include "GrProcessor.h"
13 #include "GrTypes.h" 14 #include "GrTypes.h"
14 #include "GrXferProcessor.h" 15 #include "GrXferProcessor.h"
15 #include "gl/GrGLProcessor.h" 16 #include "gl/GrGLProcessor.h"
16 #include "gl/builders/GrGLFragmentShaderBuilder.h" 17 #include "gl/builders/GrGLFragmentShaderBuilder.h"
17 #include "gl/builders/GrGLProgramBuilder.h" 18 #include "gl/builders/GrGLProgramBuilder.h"
18 19
20 static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff, bool isCoverageD rawing) {
21 /*
22 The fractional coverage is f.
23 The src and dst coeffs are Cs and Cd.
24 The dst and src colors are S and D.
25 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou rce color's alpha
26 we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
27 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss ibilities for Cd we
28 find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
29 Also, if we're directly rendering coverage (isCoverageDrawing) then coverag e is treated as
30 color by definition.
31 */
32 // TODO: Once we have a CoverageDrawing XP, we don't need to check is Covera geDrawing here
33 return kOne_GrBlendCoeff == dstCoeff ||
34 kISA_GrBlendCoeff == dstCoeff ||
35 kISC_GrBlendCoeff == dstCoeff ||
36 isCoverageDrawing;
37 }
38
19 class GrGLPorterDuffXferProcessor : public GrGLXferProcessor { 39 class GrGLPorterDuffXferProcessor : public GrGLXferProcessor {
20 public: 40 public:
21 GrGLPorterDuffXferProcessor(const GrProcessor&) {} 41 GrGLPorterDuffXferProcessor(const GrProcessor&) {}
22 42
23 virtual ~GrGLPorterDuffXferProcessor() {} 43 virtual ~GrGLPorterDuffXferProcessor() {}
24 44
25 virtual void emitCode(GrGLFPBuilder* builder, 45 virtual void emitCode(GrGLFPBuilder* builder,
26 const GrFragmentProcessor& fp, 46 const GrFragmentProcessor& fp,
27 const char* outputColor, 47 const char* outputColor,
28 const char* inputColor, 48 const char* inputColor,
29 const TransformedCoordsArray& coords, 49 const TransformedCoordsArray& coords,
30 const TextureSamplerArray& samplers) SK_OVERRIDE { 50 const TextureSamplerArray& samplers) SK_OVERRIDE {
31 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 51 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
32 fsBuilder->codeAppendf("%s = %s;", outputColor, inputColor); 52 fsBuilder->codeAppendf("%s = %s;", outputColor, inputColor);
33 } 53 }
34 54
35 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_O VERRIDE {}; 55 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_O VERRIDE {};
36 56
37 static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyB uilder* b) {}; 57 static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyB uilder* b) {};
38 58
39 private: 59 private:
40 typedef GrGLXferProcessor INHERITED; 60 typedef GrGLXferProcessor INHERITED;
41 }; 61 };
42 62
43 /////////////////////////////////////////////////////////////////////////////// 63 ///////////////////////////////////////////////////////////////////////////////
44 64
45 GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBl endCoeff dstBlend) 65 GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBl endCoeff dstBlend,
46 : fSrcBlend(srcBlend), fDstBlend(dstBlend) { 66 GrColor constant)
67 : fSrcBlend(srcBlend), fDstBlend(dstBlend), fBlendConstant(constant) {
47 this->initClassID<GrPorterDuffXferProcessor>(); 68 this->initClassID<GrPorterDuffXferProcessor>();
48 } 69 }
49 70
50 GrPorterDuffXferProcessor::~GrPorterDuffXferProcessor() { 71 GrPorterDuffXferProcessor::~GrPorterDuffXferProcessor() {
51 } 72 }
52 73
53 void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps, 74 void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps,
54 GrProcessorKeyBuilder* b) cons t { 75 GrProcessorKeyBuilder* b) cons t {
55 GrGLPorterDuffXferProcessor::GenKey(*this, caps, b); 76 GrGLPorterDuffXferProcessor::GenKey(*this, caps, b);
56 } 77 }
57 78
58 GrGLFragmentProcessor* GrPorterDuffXferProcessor::createGLInstance() const { 79 GrGLFragmentProcessor* GrPorterDuffXferProcessor::createGLInstance() const {
59 return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this)); 80 return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this));
60 } 81 }
61 82
62 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou t) const { 83 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou t) const {
63 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput); 84 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
64 } 85 }
65 86
87 GrXferProcessor::OptFlags
88 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
89 const GrProcOptInfo& coveragePOI,
90 bool isCoverageDrawing,
91 bool colorWriteDisabled,
92 bool doesStencilWrite,
93 GrColor* color, uint8_t* coverage) {
94 if (colorWriteDisabled) {
95 fSrcBlend = kZero_GrBlendCoeff;
96 fDstBlend = kOne_GrBlendCoeff;
97 }
98
99 bool srcAIsOne;
100 bool hasCoverage;
101 if (isCoverageDrawing) {
102 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque();
103 hasCoverage = false;
104 } else {
105 srcAIsOne = colorPOI.isOpaque();
106 hasCoverage = !coveragePOI.isSolidWhite();
107 }
108
109 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend ||
110 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne);
111 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend ||
112 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne);
113
114 // Optimizations when doing RGB Coverage
115 if (coveragePOI.isFourChannelOutput()) {
116 // We want to force our primary output to be alpha * Coverage, where alp ha is the alpha
117 // value of the blend the constant. We should already have valid blend c oeff's if we are at
118 // a point where we have RGB coverage. We don't need any color stages si nce the known color
119 // output is already baked into the blendConstant.
120 uint8_t alpha = GrColorUnpackA(fBlendConstant);
121 *color = GrColorPackRGBA(alpha, alpha, alpha, alpha);
122 return GrXferProcessor::kClearColorStages_OptFlag;
123 }
124
125 // When coeffs are (0,1) there is no reason to draw at all, unless
126 // stenciling is enabled. Having color writes disabled is effectively
127 // (0,1).
128 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) {
129 if (doesStencilWrite) {
130 *color = 0xffffffff;
131 return GrXferProcessor::kClearColorStages_OptFlag |
132 GrXferProcessor::kSetCoverageDrawing_OptFlag;
133 } else {
134 fDstBlend = kOne_GrBlendCoeff;
135 return GrXferProcessor::kSkipDraw_OptFlag;
136 }
137 }
138
139 // if we don't have coverage we can check whether the dst
140 // has to read at all. If not, we'll disable blending.
141 if (!hasCoverage) {
142 if (dstCoeffIsZero) {
143 if (kOne_GrBlendCoeff == fSrcBlend) {
144 // if there is no coverage and coeffs are (1,0) then we
145 // won't need to read the dst at all, it gets replaced by src
146 fDstBlend = kZero_GrBlendCoeff;
147 return GrXferProcessor::kNone_Opt;
148 } else if (kZero_GrBlendCoeff == fSrcBlend) {
149 // if the op is "clear" then we don't need to emit a color
150 // or blend, just write transparent black into the dst.
151 fSrcBlend = kOne_GrBlendCoeff;
152 fDstBlend = kZero_GrBlendCoeff;
153 *color = 0;
154 *coverage = 0xff;
155 return GrXferProcessor::kClearColorStages_OptFlag |
156 GrXferProcessor::kClearCoverageStages_OptFlag;
157 }
158 }
159 } else if (isCoverageDrawing) {
160 // we have coverage but we aren't distinguishing it from alpha by reques t.
161 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
162 } else {
163 // check whether coverage can be safely rolled into alpha
164 // of if we can skip color computation and just emit coverage
165 if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) {
166 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
167 }
168 if (dstCoeffIsZero) {
169 if (kZero_GrBlendCoeff == fSrcBlend) {
170 // the source color is not included in the blend
171 // the dst coeff is effectively zero so blend works out to:
172 // (c)(0)D + (1-c)D = (1-c)D.
173 fDstBlend = kISA_GrBlendCoeff;
174 *color = 0xffffffff;
175 return GrXferProcessor::kClearColorStages_OptFlag |
176 GrXferProcessor::kSetCoverageDrawing_OptFlag;
177 } else if (srcAIsOne) {
178 // the dst coeff is effectively zero so blend works out to:
179 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
180 // If Sa is 1 then we can replace Sa with c
181 // and set dst coeff to 1-Sa.
182 fDstBlend = kISA_GrBlendCoeff;
183 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
184 }
185 } else if (dstCoeffIsOne) {
186 // the dst coeff is effectively one so blend works out to:
187 // cS + (c)(1)D + (1-c)D = cS + D.
188 fDstBlend = kOne_GrBlendCoeff;
189 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
190 }
191 }
192
193 return GrXferProcessor::kNone_Opt;
194 }
66 /////////////////////////////////////////////////////////////////////////////// 195 ///////////////////////////////////////////////////////////////////////////////
67 196
68 GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) 197 GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst)
69 : fSrc(src), fDst(dst) { 198 : fSrcCoeff(src), fDstCoeff(dst) {
70 this->initClassID<GrPorterDuffXPFactory>(); 199 this->initClassID<GrPorterDuffXPFactory>();
71 } 200 }
72 201
73 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) { 202 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) {
74 switch (mode) { 203 switch (mode) {
75 case SkXfermode::kClear_Mode: { 204 case SkXfermode::kClear_Mode: {
76 static GrPorterDuffXPFactory gClearPDXPF(kZero_GrBlendCoeff, kZero_G rBlendCoeff); 205 static GrPorterDuffXPFactory gClearPDXPF(kZero_GrBlendCoeff, kZero_G rBlendCoeff);
77 return SkRef(&gClearPDXPF); 206 return SkRef(&gClearPDXPF);
78 break; 207 break;
79 } 208 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 case SkXfermode::kScreen_Mode: { 274 case SkXfermode::kScreen_Mode: {
146 static GrPorterDuffXPFactory gScreenPDXPF(kOne_GrBlendCoeff, kISC_Gr BlendCoeff); 275 static GrPorterDuffXPFactory gScreenPDXPF(kOne_GrBlendCoeff, kISC_Gr BlendCoeff);
147 return SkRef(&gScreenPDXPF); 276 return SkRef(&gScreenPDXPF);
148 break; 277 break;
149 } 278 }
150 default: 279 default:
151 return NULL; 280 return NULL;
152 } 281 }
153 } 282 }
154 283
155 const GrXferProcessor* GrPorterDuffXPFactory::createXferProcessor() const { 284 GrXferProcessor* GrPorterDuffXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
156 return GrPorterDuffXferProcessor::Create(fSrc, fDst); 285 const GrProcOptInfo& covPOI) const {
286 if (!covPOI.isFourChannelOutput()) {
287 return GrPorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff);
288 } else {
289 if (this->supportsRGBCoverage(colorPOI.color(), colorPOI.validFlags())) {
290 SkASSERT(kRGBA_GrColorComponentFlags == colorPOI.validFlags());
291 GrColor blendConstant = GrUnPreMulColor(colorPOI.color());
292 return GrPorterDuffXferProcessor::Create(kConstC_GrBlendCoeff, kISC_ GrBlendCoeff,
293 blendConstant);
294 } else {
295 return NULL;
296 }
297 }
157 } 298 }
158 299
159 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, 300 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/,
160 uint32_t knownColorFlags) const { 301 uint32_t knownColorFlags) const {
161 if (kOne_GrBlendCoeff == fSrc && kISA_GrBlendCoeff == fDst && 302 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff &&
162 kRGBA_GrColorComponentFlags == knownColorFlags) { 303 kRGBA_GrColorComponentFlags == knownColorFlags) {
163 return true; 304 return true;
164 } 305 }
165 return false; 306 return false;
166 } 307 }
167 308
309 bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI,
310 const GrProcOptInfo& coveragePOI,
311 bool isCoverageDrawing,
312 bool colorWriteDisabled) const {
313 bool srcAIsOne = colorPOI.isOpaque() && (!isCoverageDrawing || coveragePOI.i sOpaque());
314
315 if (colorWriteDisabled) {
316 return true;
317 }
318
319 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstCoeff ||
320 (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne);
321 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstCoeff ||
322 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne);
323
324 if ((kZero_GrBlendCoeff == fSrcCoeff && dstCoeffIsOne)) {
325 return true;
326 }
327
328 // if we don't have coverage we can check whether the dst
329 // has to read at all.
330 if (isCoverageDrawing) {
331 // we have coverage but we aren't distinguishing it from alpha by reques t.
332 return true;
333 } else {
334 // check whether coverage can be safely rolled into alpha
335 // of if we can skip color computation and just emit coverage
336 if (this->canTweakAlphaForCoverage(isCoverageDrawing)) {
337 return true;
338 }
339 if (dstCoeffIsZero) {
340 if (kZero_GrBlendCoeff == fSrcCoeff) {
341 return true;
342 } else if (srcAIsOne) {
343 return true;
344 }
345 } else if (dstCoeffIsOne) {
346 return true;
347 }
348 }
349
350 // TODO: once all SkXferEffects are XP's then we will never reads dst here s ince only XP's
351 // will readDst and PD XP's don't read dst.
352 if ((colorPOI.readsDst() || coveragePOI.readsDst()) &&
353 kOne_GrBlendCoeff == fSrcCoeff && kZero_GrBlendCoeff == fDstCoeff) {
354 return true;
355 }
356
357 return false;
358 }
359
360 bool GrPorterDuffXPFactory::willBlendWithDst(const GrProcOptInfo& colorPOI,
361 const GrProcOptInfo& coveragePOI,
362 bool isCoverageDrawing,
363 bool colorWriteDisabled) const {
364 if (!(isCoverageDrawing || coveragePOI.isSolidWhite())) {
365 return true;
366 }
367
368 // TODO: once all SkXferEffects are XP's then we will never reads dst here s ince only XP's
369 // will readDst and PD XP's don't read dst.
370 if ((!colorWriteDisabled && colorPOI.readsDst()) || coveragePOI.readsDst()) {
371 return true;
372 }
373
374 if (GrBlendCoeffRefsDst(fSrcCoeff)) {
375 return true;
376 }
377
378 bool srcAIsOne = colorPOI.isOpaque() && (!isCoverageDrawing || coveragePOI.i sOpaque());
379
380 if (!(kZero_GrBlendCoeff == fDstCoeff ||
381 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne))) {
382 return true;
383 }
384
385 return false;
386 }
387
388 bool GrPorterDuffXPFactory::canTweakAlphaForCoverage(bool isCoverageDrawing) con st {
389 return can_tweak_alpha_for_coverage(fDstCoeff, isCoverageDrawing);
390 }
391
392 bool GrPorterDuffXPFactory::getOpaqueAndKnownColor(const GrProcOptInfo& colorPOI ,
393 const GrProcOptInfo& coverage POI,
394 GrColor* solidColor,
395 uint32_t* solidColorKnownComp onents) const {
396 if (!coveragePOI.isSolidWhite()) {
397 return false;
398 }
399
400 SkASSERT((NULL == solidColor) == (NULL == solidColorKnownComponents));
401
402 GrBlendCoeff srcCoeff = fSrcCoeff;
403 GrBlendCoeff dstCoeff = fDstCoeff;
404
405 // TODO: figure out to merge this simplify with other current optimization c ode paths and
406 // eventually remove from GrBlend
407 GrSimplifyBlend(&srcCoeff, &dstCoeff, colorPOI.color(), colorPOI.validFlags( ),
408 0, 0, 0);
409
410 bool opaque = kZero_GrBlendCoeff == dstCoeff && !GrBlendCoeffRefsDst(srcCoef f);
411 if (solidColor) {
412 if (opaque) {
413 switch (srcCoeff) {
414 case kZero_GrBlendCoeff:
415 *solidColor = 0;
416 *solidColorKnownComponents = kRGBA_GrColorComponentFlags;
417 break;
418
419 case kOne_GrBlendCoeff:
420 *solidColor = colorPOI.color();
421 *solidColorKnownComponents = colorPOI.validFlags();
422 break;
423
424 // The src coeff should never refer to the src and if it refers to dst then opaque
425 // should have been false.
426 case kSC_GrBlendCoeff:
427 case kISC_GrBlendCoeff:
428 case kDC_GrBlendCoeff:
429 case kIDC_GrBlendCoeff:
430 case kSA_GrBlendCoeff:
431 case kISA_GrBlendCoeff:
432 case kDA_GrBlendCoeff:
433 case kIDA_GrBlendCoeff:
434 default:
435 SkFAIL("srcCoeff should not refer to src or dst.");
436 break;
437
438 // TODO: update this once GrPaint actually has a const color.
439 case kConstC_GrBlendCoeff:
440 case kIConstC_GrBlendCoeff:
441 case kConstA_GrBlendCoeff:
442 case kIConstA_GrBlendCoeff:
443 *solidColorKnownComponents = 0;
444 break;
445 }
446 } else {
447 solidColorKnownComponents = 0;
448 }
449 }
450 return opaque;
451 }
452
453
OLDNEW
« no previous file with comments | « src/gpu/SkGr.cpp ('k') | tests/GLProgramsTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698