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

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

Powered by Google App Engine
This is Rietveld 408576698