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

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

Issue 764643004: Create xfer processor backend. (Closed) Base URL: https://skia.googlesource.com/skia.git@xferBlendSolo
Patch Set: updated and rebased from prev cls 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 "effects/GrPorterDuffXferProcessor.h" 8 #include "effects/GrPorterDuffXferProcessor.h"
9 9
10 #include "GrBlend.h" 10 #include "GrBlend.h"
11 #include "GrDrawState.h" 11 #include "GrDrawState.h"
12 #include "GrDrawTargetCaps.h"
12 #include "GrInvariantOutput.h" 13 #include "GrInvariantOutput.h"
13 #include "GrProcessor.h" 14 #include "GrProcessor.h"
14 #include "GrTypes.h" 15 #include "GrTypes.h"
15 #include "GrXferProcessor.h" 16 #include "GrXferProcessor.h"
16 #include "gl/GrGLProcessor.h" 17 #include "gl/GrGLXferProcessor.h"
17 #include "gl/builders/GrGLFragmentShaderBuilder.h" 18 #include "gl/builders/GrGLFragmentShaderBuilder.h"
18 #include "gl/builders/GrGLProgramBuilder.h" 19 #include "gl/builders/GrGLProgramBuilder.h"
19 20
20 static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff, bool isCoverageD rawing) { 21 static bool can_tweak_alpha_for_coverage(GrBlendCoeff dstCoeff, bool isCoverageD rawing) {
21 /* 22 /*
22 The fractional coverage is f. 23 The fractional coverage is f.
23 The src and dst coeffs are Cs and Cd. 24 The src and dst coeffs are Cs and Cd.
24 The dst and src colors are S and D. 25 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 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 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 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 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 Also, if we're directly rendering coverage (isCoverageDrawing) then coverag e is treated as
30 color by definition. 31 color by definition.
31 */ 32 */
32 // TODO: Once we have a CoverageDrawing XP, we don't need to check is Covera geDrawing here 33 // TODO: Once we have a CoverageDrawing XP, we don't need to check is Covera geDrawing here
33 return kOne_GrBlendCoeff == dstCoeff || 34 return kOne_GrBlendCoeff == dstCoeff ||
34 kISA_GrBlendCoeff == dstCoeff || 35 kISA_GrBlendCoeff == dstCoeff ||
35 kISC_GrBlendCoeff == dstCoeff || 36 kISC_GrBlendCoeff == dstCoeff ||
36 isCoverageDrawing; 37 isCoverageDrawing;
37 } 38 }
38 39
39 class GrGLPorterDuffXferProcessor : public GrGLXferProcessor { 40 class GrGLPorterDuffXferProcessor : public GrGLXferProcessor {
40 public: 41 public:
41 GrGLPorterDuffXferProcessor(const GrProcessor&) {} 42 GrGLPorterDuffXferProcessor(const GrProcessor&) {}
42 43
43 virtual ~GrGLPorterDuffXferProcessor() {} 44 virtual ~GrGLPorterDuffXferProcessor() {}
44 45
45 virtual void emitCode(GrGLFPBuilder* builder, 46 virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
46 const GrFragmentProcessor& fp, 47 const GrPorterDuffXferProcessor& xp = args.fXP.cast<GrPorterDuffXferProc essor>();
47 const char* outputColor, 48 GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
48 const char* inputColor, 49 if (xp.hasSecondaryOutput()) {
49 const TransformedCoordsArray& coords, 50 switch(xp.secondaryOutputType()) {
50 const TextureSamplerArray& samplers) SK_OVERRIDE { 51 case GrPorterDuffXferProcessor::kCoverage_SecondaryOutputType:
51 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); 52 fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, ar gs.fInputCoverage);
52 fsBuilder->codeAppendf("%s = %s;", outputColor, inputColor); 53 break;
54 case GrPorterDuffXferProcessor::kCoverageISA_SecondaryOutputType :
55 fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;",
56 args.fOutputSecondary, args.fInputCol or,
57 args.fInputCoverage);
58 break;
59 case GrPorterDuffXferProcessor::kCoverageISC_SecondaryOutputType :
60 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;",
61 args.fOutputSecondary, args.fInputCol or,
62 args.fInputCoverage);
63 break;
64 default:
65 SkFAIL("Unexpected Secondary Output");
66 }
67 }
68
69 fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInput Color,
70 args.fInputCoverage);
53 } 71 }
54 72
55 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_O VERRIDE {}; 73 virtual void setData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVERRIDE {};
56 74
57 static void GenKey(const GrProcessor&, const GrGLCaps& caps, GrProcessorKeyB uilder* b) {}; 75 static void GenKey(const GrProcessor& processor, const GrGLCaps& caps,
76 GrProcessorKeyBuilder* b) {
77 const GrPorterDuffXferProcessor& xp = processor.cast<GrPorterDuffXferPro cessor>();
78 b->add32(xp.secondaryOutputType());
79 };
58 80
59 private: 81 private:
82
joshualitt 2014/12/08 19:46:40 I'm not saying you HAVE to delete this space, but
egdaniel 2014/12/09 21:10:46 Done.
60 typedef GrGLXferProcessor INHERITED; 83 typedef GrGLXferProcessor INHERITED;
61 }; 84 };
62 85
63 /////////////////////////////////////////////////////////////////////////////// 86 ///////////////////////////////////////////////////////////////////////////////
64 87
65 GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBl endCoeff dstBlend, 88 GrPorterDuffXferProcessor::GrPorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBl endCoeff dstBlend,
66 GrColor constant) 89 GrColor constant)
67 : fSrcBlend(srcBlend), fDstBlend(dstBlend), fBlendConstant(constant) { 90 : fSrcBlend(srcBlend)
91 , fDstBlend(dstBlend)
92 , fBlendConstant(constant)
93 , fSecondaryOutputType(kNone_SecondaryOutputType) {
68 this->initClassID<GrPorterDuffXferProcessor>(); 94 this->initClassID<GrPorterDuffXferProcessor>();
69 } 95 }
70 96
71 GrPorterDuffXferProcessor::~GrPorterDuffXferProcessor() { 97 GrPorterDuffXferProcessor::~GrPorterDuffXferProcessor() {
72 } 98 }
73 99
74 void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps, 100 void GrPorterDuffXferProcessor::getGLProcessorKey(const GrGLCaps& caps,
75 GrProcessorKeyBuilder* b) cons t { 101 GrProcessorKeyBuilder* b) cons t {
76 GrGLPorterDuffXferProcessor::GenKey(*this, caps, b); 102 GrGLPorterDuffXferProcessor::GenKey(*this, caps, b);
77 } 103 }
78 104
79 GrGLFragmentProcessor* GrPorterDuffXferProcessor::createGLInstance() const { 105 GrGLXferProcessor* GrPorterDuffXferProcessor::createGLInstance() const {
80 return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this)); 106 return SkNEW_ARGS(GrGLPorterDuffXferProcessor, (*this));
81 } 107 }
82 108
83 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou t) const { 109 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou t) const {
84 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); 110 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput);
85 } 111 }
86 112
87 GrXferProcessor::OptFlags 113 GrXferProcessor::OptFlags
88 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, 114 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
89 const GrProcOptInfo& coveragePOI, 115 const GrProcOptInfo& coveragePOI,
90 bool isCoverageDrawing, 116 bool isCoverageDrawing,
91 bool colorWriteDisabled, 117 bool colorWriteDisabled,
92 bool doesStencilWrite, 118 bool doesStencilWrite,
93 GrColor* color, uint8_t* coverage) { 119 GrColor* color, uint8_t* coverage,
120 const GrDrawTargetCaps& caps) {
121 GrXferProcessor::OptFlags optFlags = this->internalGetOptimizations(colorPOI ,
122 coverage POI,
123 isCovera geDrawing,
124 colorWri teDisabled,
125 doesSten cilWrite,
126 color,
127 coverage );
128
129 this->calcOutputTypes(optFlags, caps, isCoverageDrawing,
130 colorPOI.readsDst() || coveragePOI.readsDst());
joshualitt 2014/12/08 19:46:41 I thought only xps read dst?
bsalomon 2014/12/08 19:58:59 AFACT that has to wait until XPs are written for t
egdaniel 2014/12/09 21:10:46 Yes this is correct.
131 return optFlags;
132 }
133
134 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla gs,
135 const GrDrawTargetCaps& caps,
136 bool isCoverageDrawing, bool rea dsDst) {
137 // If we do have coverage determine whether it matters. Dual source blendin g is expensive so
138 // we don't do it if we are doing coverage drawing. If we aren't then We al ways do dual source
139 // blending if we have any effective coverage stages OR the geometry process or doesn't emits
140 // solid coverage.
141 // TODO move the gp logic into the GP base class
joshualitt 2014/12/08 19:46:41 remove todo
egdaniel 2014/12/09 21:10:46 Done.
142
143 if (!(optFlags & kSetCoverageDrawing_OptFlag) && !isCoverageDrawing) {
144 if (caps.dualSourceBlendingSupport()) {
145 if (kZero_GrBlendCoeff == fDstBlend) {
146 // write the coverage value to second color
147 fSecondaryOutputType = kCoverage_SecondaryOutputType;
148 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
149 } else if (kSA_GrBlendCoeff == fDstBlend) {
150 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
151 fSecondaryOutputType = kCoverageISA_SecondaryOutputType;
152 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
153 } else if (kSC_GrBlendCoeff == fDstBlend) {
154 // SA dst coeff becomes 1-(1-SA)*coverage when dst is partially covered.
155 fSecondaryOutputType = kCoverageISC_SecondaryOutputType;
156 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff;
157 }
158 }
159 }
160 }
161
162 GrXferProcessor::OptFlags
163 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO I,
164 const GrProcOptInfo& coverag ePOI,
165 bool isCoverageDrawing,
166 bool colorWriteDisabled,
167 bool doesStencilWrite,
168 GrColor* color, uint8_t* cov erage) {
94 if (colorWriteDisabled) { 169 if (colorWriteDisabled) {
95 fSrcBlend = kZero_GrBlendCoeff; 170 fSrcBlend = kZero_GrBlendCoeff;
96 fDstBlend = kOne_GrBlendCoeff; 171 fDstBlend = kOne_GrBlendCoeff;
97 } 172 }
98 173
99 bool srcAIsOne; 174 bool srcAIsOne;
100 bool hasCoverage; 175 bool hasCoverage;
101 if (isCoverageDrawing) { 176 if (isCoverageDrawing) {
102 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque(); 177 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque();
103 hasCoverage = false; 178 hasCoverage = false;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 } else if (dstCoeffIsOne) { 260 } else if (dstCoeffIsOne) {
186 // the dst coeff is effectively one so blend works out to: 261 // the dst coeff is effectively one so blend works out to:
187 // cS + (c)(1)D + (1-c)D = cS + D. 262 // cS + (c)(1)D + (1-c)D = cS + D.
188 fDstBlend = kOne_GrBlendCoeff; 263 fDstBlend = kOne_GrBlendCoeff;
189 return GrXferProcessor::kSetCoverageDrawing_OptFlag; 264 return GrXferProcessor::kSetCoverageDrawing_OptFlag;
190 } 265 }
191 } 266 }
192 267
193 return GrXferProcessor::kNone_Opt; 268 return GrXferProcessor::kNone_Opt;
194 } 269 }
270
271 bool GrPorterDuffXferProcessor::hasSecondaryOutput() const {
272 return kNone_SecondaryOutputType != fSecondaryOutputType;
273 }
274
195 /////////////////////////////////////////////////////////////////////////////// 275 ///////////////////////////////////////////////////////////////////////////////
196 276
197 GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst) 277 GrPorterDuffXPFactory::GrPorterDuffXPFactory(GrBlendCoeff src, GrBlendCoeff dst)
198 : fSrcCoeff(src), fDstCoeff(dst) { 278 : fSrcCoeff(src), fDstCoeff(dst) {
199 this->initClassID<GrPorterDuffXPFactory>(); 279 this->initClassID<GrPorterDuffXPFactory>();
200 } 280 }
201 281
202 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) { 282 GrXPFactory* GrPorterDuffXPFactory::Create(SkXfermode::Mode mode) {
203 switch (mode) { 283 switch (mode) {
204 case SkXfermode::kClear_Mode: { 284 case SkXfermode::kClear_Mode: {
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 *solidColorKnownComponents = 0; 523 *solidColorKnownComponents = 0;
444 break; 524 break;
445 } 525 }
446 } else { 526 } else {
447 solidColorKnownComponents = 0; 527 solidColorKnownComponents = 0;
448 } 528 }
449 } 529 }
450 return opaque; 530 return opaque;
451 } 531 }
452 532
533 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
453 534
535 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random,
536 GrContext*,
537 const GrDrawTargetCaps&,
538 GrTexture*[]) {
539 GrBlendCoeff src;
540 do {
541 src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff));
542 } while (GrBlendCoeffRefsSrc(src));
543
544 GrBlendCoeff dst;
545 do {
546 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff));
547 } while (GrBlendCoeffRefsDst(dst));
548
549 return GrPorterDuffXPFactory::Create(src, dst);
550 }
551
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698