OLD | NEW |
---|---|
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" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
52 /////////////////////////////////////////////////////////////////////////// | 52 /////////////////////////////////////////////////////////////////////////// |
53 /// @name Stage Output Types | 53 /// @name Stage Output Types |
54 //// | 54 //// |
55 | 55 |
56 enum PrimaryOutputType { | 56 enum PrimaryOutputType { |
57 kNone_PrimaryOutputType, | 57 kNone_PrimaryOutputType, |
58 kColor_PrimaryOutputType, | 58 kColor_PrimaryOutputType, |
59 kCoverage_PrimaryOutputType, | 59 kCoverage_PrimaryOutputType, |
60 // Modulate color and coverage, write result as the color output. | 60 // Modulate color and coverage, write result as the color output. |
61 kModulate_PrimaryOutputType, | 61 kModulate_PrimaryOutputType, |
62 // Custom Porter-Duff output, used for when we explictly are reading the dst and blending | |
63 // in the shader. Secondary Output must be none if you use this. The cus tom blend uses the | |
64 // equation: cov * (coeffS * S + coeffD * D) + (1 - cov) * D | |
65 kCustom_PrimaryOutputType | |
62 }; | 66 }; |
63 | 67 |
64 enum SecondaryOutputType { | 68 enum SecondaryOutputType { |
65 // There is no secondary output | 69 // There is no secondary output |
66 kNone_SecondaryOutputType, | 70 kNone_SecondaryOutputType, |
67 // Writes coverage as the secondary output. Only set if dual source blen ding is supported | 71 // Writes coverage as the secondary output. Only set if dual source blen ding is supported |
68 // and primary output is kModulate. | 72 // and primary output is kModulate. |
69 kCoverage_SecondaryOutputType, | 73 kCoverage_SecondaryOutputType, |
70 // Writes coverage * (1 - colorA) as the secondary output. Only set if d ual source blending | 74 // Writes coverage * (1 - colorA) as the secondary output. Only set if d ual source blending |
71 // is supported and primary output is kModulate. | 75 // is supported and primary output is kModulate. |
72 kCoverageISA_SecondaryOutputType, | 76 kCoverageISA_SecondaryOutputType, |
73 // Writes coverage * (1 - colorRGBA) as the secondary output. Only set i f dual source | 77 // Writes coverage * (1 - colorRGBA) as the secondary output. Only set i f dual source |
74 // blending is supported and primary output is kModulate. | 78 // blending is supported and primary output is kModulate. |
75 kCoverageISC_SecondaryOutputType, | 79 kCoverageISC_SecondaryOutputType, |
76 | 80 |
77 kSecondaryOutputTypeCnt, | 81 kSecondaryOutputTypeCnt, |
78 }; | 82 }; |
79 | 83 |
80 PrimaryOutputType primaryOutputType() const { return fPrimaryOutputType; } | 84 PrimaryOutputType primaryOutputType() const { return fPrimaryOutputType; } |
81 SecondaryOutputType secondaryOutputType() const { return fSecondaryOutputTyp e; } | 85 SecondaryOutputType secondaryOutputType() const { return fSecondaryOutputTyp e; } |
82 | 86 |
83 GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI, | 87 GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI, |
84 const GrProcOptInfo& coveragePOI, | 88 const GrProcOptInfo& coveragePOI, |
85 bool doesStencilWrite, | 89 bool doesStencilWrite, |
86 GrColor* overrideColor, | 90 GrColor* overrideColor, |
87 const GrDrawTargetCaps& caps) SK_ OVERRIDE; | 91 const GrDrawTargetCaps& caps) SK_ OVERRIDE; |
88 | 92 |
89 void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE { | 93 void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE { |
90 blendInfo->fSrcBlend = fSrcBlend; | 94 if (!this->willReadDstColor()) { |
91 blendInfo->fDstBlend = fDstBlend; | 95 blendInfo->fSrcBlend = fSrcBlend; |
96 blendInfo->fDstBlend = fDstBlend; | |
97 } else { | |
98 blendInfo->fSrcBlend = kOne_GrBlendCoeff; | |
99 blendInfo->fDstBlend = kZero_GrBlendCoeff; | |
100 } | |
92 blendInfo->fBlendConstant = fBlendConstant; | 101 blendInfo->fBlendConstant = fBlendConstant; |
93 } | 102 } |
94 | 103 |
104 GrBlendCoeff getSrcBlend() const { return fSrcBlend; } | |
105 GrBlendCoeff getDstBlend() const { return fDstBlend; } | |
106 | |
95 private: | 107 private: |
96 PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColo r constant, | 108 PorterDuffXferProcessor(GrBlendCoeff srcBlend, GrBlendCoeff dstBlend, GrColo r constant, |
97 const GrDeviceCoordTexture* dstCopy, bool willReadDs tColor); | 109 const GrDeviceCoordTexture* dstCopy, bool willReadDs tColor); |
98 | 110 |
99 void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) con st SK_OVERRIDE; | 111 void onGetGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) con st SK_OVERRIDE; |
100 | 112 |
101 bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE { | 113 bool onIsEqual(const GrXferProcessor& xpBase) const SK_OVERRIDE { |
102 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor> (); | 114 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor> (); |
103 if (fSrcBlend != xp.fSrcBlend || | 115 if (fSrcBlend != xp.fSrcBlend || |
104 fDstBlend != xp.fDstBlend || | 116 fDstBlend != xp.fDstBlend || |
(...skipping 16 matching lines...) Expand all Loading... | |
121 GrBlendCoeff fDstBlend; | 133 GrBlendCoeff fDstBlend; |
122 GrColor fBlendConstant; | 134 GrColor fBlendConstant; |
123 PrimaryOutputType fPrimaryOutputType; | 135 PrimaryOutputType fPrimaryOutputType; |
124 SecondaryOutputType fSecondaryOutputType; | 136 SecondaryOutputType fSecondaryOutputType; |
125 | 137 |
126 typedef GrXferProcessor INHERITED; | 138 typedef GrXferProcessor INHERITED; |
127 }; | 139 }; |
128 | 140 |
129 /////////////////////////////////////////////////////////////////////////////// | 141 /////////////////////////////////////////////////////////////////////////////// |
130 | 142 |
143 bool append_porterduff_blend(GrGLFPFragmentBuilder* fsBuilder, GrBlendCoeff coef f, | |
144 const char* colorName, const char* srcColorName, | |
145 const char* dstColorName, bool hasPrevious) { | |
146 if (kZero_GrBlendCoeff == coeff) { | |
147 return hasPrevious; | |
148 } else { | |
149 if (hasPrevious) { | |
150 fsBuilder->codeAppend(" + "); | |
151 } | |
152 fsBuilder->codeAppendf("%s", colorName); | |
153 switch (coeff) { | |
154 case kOne_GrBlendCoeff: | |
155 break; | |
156 case kSC_GrBlendCoeff: | |
157 fsBuilder->codeAppendf(" * %s", srcColorName); | |
158 break; | |
159 case kISC_GrBlendCoeff: | |
160 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", srcColorName); | |
161 break; | |
162 case kDC_GrBlendCoeff: | |
163 fsBuilder->codeAppendf(" * %s", dstColorName); | |
164 break; | |
165 case kIDC_GrBlendCoeff: | |
166 fsBuilder->codeAppendf(" * (vec4(1.0) - %s)", dstColorName); | |
167 break; | |
168 case kSA_GrBlendCoeff: | |
169 fsBuilder->codeAppendf(" * %s.a", srcColorName); | |
170 break; | |
171 case kISA_GrBlendCoeff: | |
172 fsBuilder->codeAppendf(" * (1.0 - %s.a)", srcColorName); | |
173 break; | |
174 case kDA_GrBlendCoeff: | |
175 fsBuilder->codeAppendf(" * %s.a", dstColorName); | |
176 break; | |
177 case kIDA_GrBlendCoeff: | |
178 fsBuilder->codeAppendf(" * (1.0 - %s.a)", dstColorName); | |
179 break; | |
180 default: | |
181 SkFAIL("Unsupported Blend Coeff"); | |
182 } | |
183 return true; | |
184 } | |
185 } | |
186 | |
131 class GLPorterDuffXferProcessor : public GrGLXferProcessor { | 187 class GLPorterDuffXferProcessor : public GrGLXferProcessor { |
132 public: | 188 public: |
133 GLPorterDuffXferProcessor(const GrProcessor&) {} | 189 GLPorterDuffXferProcessor(const GrProcessor&) {} |
134 | 190 |
135 virtual ~GLPorterDuffXferProcessor() {} | 191 virtual ~GLPorterDuffXferProcessor() {} |
136 | 192 |
137 static void GenKey(const GrProcessor& processor, const GrGLCaps& caps, | 193 static void GenKey(const GrProcessor& processor, const GrGLCaps& caps, |
138 GrProcessorKeyBuilder* b) { | 194 GrProcessorKeyBuilder* b) { |
139 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcess or>(); | 195 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcess or>(); |
140 b->add32(xp.primaryOutputType()); | 196 b->add32(xp.primaryOutputType()); |
141 b->add32(xp.secondaryOutputType()); | 197 b->add32(xp.secondaryOutputType()); |
198 if (xp.willReadDstColor()) { | |
199 b->add32(xp.getSrcBlend()); | |
200 b->add32(xp.getDstBlend()); | |
201 } | |
142 }; | 202 }; |
143 | 203 |
144 private: | 204 private: |
145 void onEmitCode(const EmitArgs& args) SK_OVERRIDE { | 205 void onEmitCode(const EmitArgs& args) SK_OVERRIDE { |
146 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso r>(); | 206 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso r>(); |
147 GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); | 207 GrGLFPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
148 if (xp.hasSecondaryOutput()) { | 208 if (PorterDuffXferProcessor::kCustom_PrimaryOutputType != xp.primaryOutp utType()) { |
149 switch(xp.secondaryOutputType()) { | 209 SkASSERT(!xp.willReadDstColor()); |
150 case PorterDuffXferProcessor::kCoverage_SecondaryOutputType: | 210 if (xp.hasSecondaryOutput()) { |
bsalomon
2015/02/11 15:53:31
can we skip the vcall/extra branch here since seco
| |
151 fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary, ar gs.fInputCoverage); | 211 switch(xp.secondaryOutputType()) { |
212 case PorterDuffXferProcessor::kCoverage_SecondaryOutputType: | |
213 fsBuilder->codeAppendf("%s = %s;", args.fOutputSecondary , | |
214 args.fInputCoverage); | |
215 break; | |
216 case PorterDuffXferProcessor::kCoverageISA_SecondaryOutputTy pe: | |
217 fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", | |
218 args.fOutputSecondary, args.fInpu tColor, | |
219 args.fInputCoverage); | |
220 break; | |
221 case PorterDuffXferProcessor::kCoverageISC_SecondaryOutputTy pe: | |
222 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", | |
223 args.fOutputSecondary, args.fInpu tColor, | |
224 args.fInputCoverage); | |
225 break; | |
226 default: | |
227 SkFAIL("Unexpected Secondary Output"); | |
228 } | |
229 } | |
230 | |
231 switch (xp.primaryOutputType()) { | |
232 case PorterDuffXferProcessor::kNone_PrimaryOutputType: | |
233 fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary) ; | |
152 break; | 234 break; |
153 case PorterDuffXferProcessor::kCoverageISA_SecondaryOutputType: | 235 case PorterDuffXferProcessor::kColor_PrimaryOutputType: |
154 fsBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", | 236 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args .fInputColor); |
155 args.fOutputSecondary, args.fInputCol or, | |
156 args.fInputCoverage); | |
157 break; | 237 break; |
158 case PorterDuffXferProcessor::kCoverageISC_SecondaryOutputType: | 238 case PorterDuffXferProcessor::kCoverage_PrimaryOutputType: |
159 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", | 239 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args .fInputCoverage); |
160 args.fOutputSecondary, args.fInputCol or, | 240 break; |
241 case PorterDuffXferProcessor::kModulate_PrimaryOutputType: | |
242 fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor, | |
161 args.fInputCoverage); | 243 args.fInputCoverage); |
162 break; | 244 break; |
163 default: | 245 default: |
164 SkFAIL("Unexpected Secondary Output"); | 246 SkFAIL("Unexpected Primary Output"); |
165 } | 247 } |
166 } | 248 } else { |
167 | 249 SkASSERT(xp.willReadDstColor()); |
168 switch (xp.primaryOutputType()) { | 250 |
169 case PorterDuffXferProcessor::kNone_PrimaryOutputType: | 251 const char* dstColor = fsBuilder->dstColor(); |
170 fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary); | 252 |
171 break; | 253 fsBuilder->codeAppend("vec4 colorBlend ="); |
172 case PorterDuffXferProcessor::kColor_PrimaryOutputType: | 254 // append src blend |
173 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fIn putColor); | 255 bool didAppend = append_porterduff_blend(fsBuilder, xp.getSrcBlend() , |
bsalomon
2015/02/11 15:53:31
maybe append_porterduff_term?
| |
174 break; | 256 args.fInputColor, args.fInp utColor, |
175 case PorterDuffXferProcessor::kCoverage_PrimaryOutputType: | 257 dstColor, false); |
176 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fIn putCoverage); | 258 // append dst blend |
177 break; | 259 SkAssertResult(append_porterduff_blend(fsBuilder, xp.getDstBlend(), |
178 case PorterDuffXferProcessor::kModulate_PrimaryOutputType: | 260 dstColor, args.fInputColor, |
179 fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, arg s.fInputColor, | 261 dstColor, didAppend)); |
180 args.fInputCoverage); | 262 fsBuilder->codeAppend(";"); |
181 break; | 263 |
182 default: | 264 fsBuilder->codeAppendf("%s = %s * colorBlend + (vec4(1.0) - %s) * %s ;", |
bsalomon
2015/02/11 15:53:31
do we know if cov is 4 chan here? can we treat it
egdaniel
2015/02/13 14:19:14
In our current system we know that cov will be 4 c
| |
183 SkFAIL("Unexpected Primary Output"); | 265 args.fOutputPrimary, args.fInputCoverage, arg s.fInputCoverage, |
266 dstColor); | |
184 } | 267 } |
185 } | 268 } |
186 | 269 |
187 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVE RRIDE {}; | 270 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) SK_OVE RRIDE {}; |
188 | 271 |
189 typedef GrGLXferProcessor INHERITED; | 272 typedef GrGLXferProcessor INHERITED; |
190 }; | 273 }; |
191 | 274 |
192 /////////////////////////////////////////////////////////////////////////////// | 275 /////////////////////////////////////////////////////////////////////////////// |
193 | 276 |
194 PorterDuffXferProcessor::PorterDuffXferProcessor(GrBlendCoeff srcBlend, | 277 PorterDuffXferProcessor::PorterDuffXferProcessor(GrBlendCoeff srcBlend, |
195 GrBlendCoeff dstBlend, | 278 GrBlendCoeff dstBlend, |
196 GrColor constant, | 279 GrColor constant, |
197 const GrDeviceCoordTexture* dst Copy, | 280 const GrDeviceCoordTexture* dst Copy, |
198 bool willReadDstColor) | 281 bool willReadDstColor) |
199 : fSrcBlend(srcBlend) | 282 : INHERITED(dstCopy, willReadDstColor) |
283 , fSrcBlend(srcBlend) | |
200 , fDstBlend(dstBlend) | 284 , fDstBlend(dstBlend) |
201 , fBlendConstant(constant) | 285 , fBlendConstant(constant) |
202 , fPrimaryOutputType(kModulate_PrimaryOutputType) | 286 , fPrimaryOutputType(kModulate_PrimaryOutputType) |
203 , fSecondaryOutputType(kNone_SecondaryOutputType) { | 287 , fSecondaryOutputType(kNone_SecondaryOutputType) { |
204 this->initClassID<PorterDuffXferProcessor>(); | 288 this->initClassID<PorterDuffXferProcessor>(); |
205 } | 289 } |
206 | 290 |
207 PorterDuffXferProcessor::~PorterDuffXferProcessor() { | 291 PorterDuffXferProcessor::~PorterDuffXferProcessor() { |
208 } | 292 } |
209 | 293 |
(...skipping 27 matching lines...) Expand all Loading... | |
237 coveragePOI, | 321 coveragePOI, |
238 doesStencilWrite); | 322 doesStencilWrite); |
239 } | 323 } |
240 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite()); | 324 this->calcOutputTypes(optFlags, caps, coveragePOI.isSolidWhite()); |
241 return optFlags; | 325 return optFlags; |
242 } | 326 } |
243 | 327 |
244 void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags , | 328 void PorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags , |
245 const GrDrawTargetCaps& caps, | 329 const GrDrawTargetCaps& caps, |
246 bool hasSolidCoverage) { | 330 bool hasSolidCoverage) { |
331 if (this->willReadDstColor()) { | |
332 fPrimaryOutputType = kCustom_PrimaryOutputType; | |
333 return; | |
334 } | |
335 | |
247 if (optFlags & kIgnoreColor_OptFlag) { | 336 if (optFlags & kIgnoreColor_OptFlag) { |
248 if (optFlags & kIgnoreCoverage_OptFlag) { | 337 if (optFlags & kIgnoreCoverage_OptFlag) { |
249 fPrimaryOutputType = kNone_PrimaryOutputType; | 338 fPrimaryOutputType = kNone_PrimaryOutputType; |
250 return; | 339 return; |
251 } else { | 340 } else { |
252 fPrimaryOutputType = kCoverage_PrimaryOutputType; | 341 fPrimaryOutputType = kCoverage_PrimaryOutputType; |
253 return; | 342 return; |
254 } | 343 } |
255 } else if (optFlags & kIgnoreCoverage_OptFlag) { | 344 } else if (optFlags & kIgnoreCoverage_OptFlag) { |
256 fPrimaryOutputType = kColor_PrimaryOutputType; | 345 fPrimaryOutputType = kColor_PrimaryOutputType; |
(...skipping 20 matching lines...) Expand all Loading... | |
277 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; | 366 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; |
278 } | 367 } |
279 } | 368 } |
280 } | 369 } |
281 } | 370 } |
282 | 371 |
283 GrXferProcessor::OptFlags | 372 GrXferProcessor::OptFlags |
284 PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, | 373 PorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPOI, |
285 const GrProcOptInfo& coverageP OI, | 374 const GrProcOptInfo& coverageP OI, |
286 bool doesStencilWrite) { | 375 bool doesStencilWrite) { |
287 bool srcAIsOne; | 376 if (this->willReadDstColor()) { |
288 bool hasCoverage; | 377 return GrXferProcessor::kNone_Opt; |
378 } | |
289 | 379 |
290 srcAIsOne = colorPOI.isOpaque(); | 380 bool srcAIsOne = colorPOI.isOpaque(); |
291 hasCoverage = !coveragePOI.isSolidWhite(); | 381 bool hasCoverage = !coveragePOI.isSolidWhite(); |
292 | 382 |
293 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || | 383 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || |
294 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); | 384 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); |
295 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || | 385 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || |
296 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); | 386 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); |
297 | 387 |
298 // When coeffs are (0,1) there is no reason to draw at all, unless | 388 // When coeffs are (0,1) there is no reason to draw at all, unless |
299 // stenciling is enabled. Having color writes disabled is effectively | 389 // stenciling is enabled. Having color writes disabled is effectively |
300 // (0,1). | 390 // (0,1). |
301 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { | 391 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
446 static GrPorterDuffXPFactory gScreenPDXPF(kOne_GrBlendCoeff, kISC_Gr BlendCoeff); | 536 static GrPorterDuffXPFactory gScreenPDXPF(kOne_GrBlendCoeff, kISC_Gr BlendCoeff); |
447 return SkRef(&gScreenPDXPF); | 537 return SkRef(&gScreenPDXPF); |
448 break; | 538 break; |
449 } | 539 } |
450 default: | 540 default: |
451 return NULL; | 541 return NULL; |
452 } | 542 } |
453 } | 543 } |
454 | 544 |
455 GrXferProcessor* | 545 GrXferProcessor* |
456 GrPorterDuffXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI, | 546 GrPorterDuffXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps, |
547 const GrProcOptInfo& colorPOI, | |
457 const GrProcOptInfo& covPOI, | 548 const GrProcOptInfo& covPOI, |
458 const GrDeviceCoordTexture* dstCopy ) const { | 549 const GrDeviceCoordTexture* dstCopy ) const { |
459 if (!covPOI.isFourChannelOutput()) { | 550 if (!covPOI.isFourChannelOutput()) { |
460 return PorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy, | 551 return PorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy, |
461 this->willReadDstColor(colorPOI, covPOI)); | 552 this->willReadDstColor(caps, colo rPOI, covPOI)); |
462 } else { | 553 } else { |
463 if (this->supportsRGBCoverage(colorPOI.color(), colorPOI.validFlags())) { | 554 if (this->supportsRGBCoverage(colorPOI.color(), colorPOI.validFlags())) { |
464 SkASSERT(kRGBA_GrColorComponentFlags == colorPOI.validFlags()); | 555 SkASSERT(kRGBA_GrColorComponentFlags == colorPOI.validFlags()); |
465 GrColor blendConstant = GrUnPreMulColor(colorPOI.color()); | 556 GrColor blendConstant = GrUnPreMulColor(colorPOI.color()); |
466 return PorterDuffXferProcessor::Create(kConstC_GrBlendCoeff, kISC_Gr BlendCoeff, | 557 return PorterDuffXferProcessor::Create(kConstC_GrBlendCoeff, kISC_Gr BlendCoeff, |
467 blendConstant, dstCopy, | 558 blendConstant, dstCopy, |
468 this->willReadDstColor(colorP OI, covPOI)); | 559 this->willReadDstColor(caps, colorPOI, covPOI)); |
469 } else { | 560 } else { |
470 return NULL; | 561 return NULL; |
471 } | 562 } |
472 } | 563 } |
473 } | 564 } |
474 | 565 |
475 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, | 566 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, |
476 uint32_t knownColorFlags) const { | 567 uint32_t knownColorFlags) const { |
477 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && | 568 if (kOne_GrBlendCoeff == fSrcCoeff && kISA_GrBlendCoeff == fDstCoeff && |
478 kRGBA_GrColorComponentFlags == knownColorFlags) { | 569 kRGBA_GrColorComponentFlags == knownColorFlags) { |
479 return true; | 570 return true; |
480 } | 571 } |
481 return false; | 572 return false; |
482 } | 573 } |
483 | 574 |
484 bool GrPorterDuffXPFactory::canApplyCoverage(const GrProcOptInfo& colorPOI, | |
485 const GrProcOptInfo& coveragePOI) c onst { | |
486 bool srcAIsOne = colorPOI.isOpaque(); | |
487 | |
488 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstCoeff || | |
489 (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne); | |
490 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstCoeff || | |
491 (kISA_GrBlendCoeff == fDstCoeff && srcAIsOne); | |
492 | |
493 if ((kZero_GrBlendCoeff == fSrcCoeff && dstCoeffIsOne)) { | |
494 return true; | |
495 } | |
496 | |
497 // if we don't have coverage we can check whether the dst | |
498 // has to read at all. | |
499 // check whether coverage can be safely rolled into alpha | |
500 // of if we can skip color computation and just emit coverage | |
501 if (this->canTweakAlphaForCoverage()) { | |
502 return true; | |
503 } | |
504 if (dstCoeffIsZero) { | |
505 if (kZero_GrBlendCoeff == fSrcCoeff) { | |
506 return true; | |
507 } else if (srcAIsOne) { | |
508 return true; | |
509 } | |
510 } else if (dstCoeffIsOne) { | |
511 return true; | |
512 } | |
513 | |
514 return false; | |
515 } | |
516 | |
517 bool GrPorterDuffXPFactory::canTweakAlphaForCoverage() const { | 575 bool GrPorterDuffXPFactory::canTweakAlphaForCoverage() const { |
518 return can_tweak_alpha_for_coverage(fDstCoeff); | 576 return can_tweak_alpha_for_coverage(fDstCoeff); |
519 } | 577 } |
520 | 578 |
521 void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, | 579 void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, |
522 const GrProcOptInfo& coveragePOI, | 580 const GrProcOptInfo& coveragePOI, |
523 GrXPFactory::InvariantOutput* out put) const { | 581 GrXPFactory::InvariantOutput* out put) const { |
524 if (!coveragePOI.isSolidWhite()) { | 582 if (!coveragePOI.isSolidWhite()) { |
525 output->fWillBlendWithDst = true; | 583 output->fWillBlendWithDst = true; |
526 output->fBlendedColorFlags = 0; | 584 output->fBlendedColorFlags = 0; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
580 case kIConstC_GrBlendCoeff: | 638 case kIConstC_GrBlendCoeff: |
581 case kConstA_GrBlendCoeff: | 639 case kConstA_GrBlendCoeff: |
582 case kIConstA_GrBlendCoeff: | 640 case kIConstA_GrBlendCoeff: |
583 output->fBlendedColorFlags = 0; | 641 output->fBlendedColorFlags = 0; |
584 break; | 642 break; |
585 } | 643 } |
586 | 644 |
587 output->fWillBlendWithDst = false; | 645 output->fWillBlendWithDst = false; |
588 } | 646 } |
589 | 647 |
590 bool GrPorterDuffXPFactory::willReadDstColor(const GrProcOptInfo& colorPOI, | 648 bool GrPorterDuffXPFactory::willReadDstColor(const GrDrawTargetCaps& caps, |
649 const GrProcOptInfo& colorPOI, | |
591 const GrProcOptInfo& coveragePOI) c onst { | 650 const GrProcOptInfo& coveragePOI) c onst { |
592 return false; | 651 // We can always blend correctly if we have dual source blending. |
652 if (caps.dualSourceBlendingSupport()) { | |
653 return false; | |
654 } | |
655 | |
656 if (this->canTweakAlphaForCoverage()) { | |
657 return false; | |
658 } | |
659 | |
660 bool srcAIsOne = colorPOI.isOpaque(); | |
661 | |
662 if (kZero_GrBlendCoeff == fDstCoeff) { | |
663 if (kZero_GrBlendCoeff == fSrcCoeff || srcAIsOne) { | |
664 return false; | |
665 } | |
666 } | |
667 | |
668 // Reduces to: coeffS * (Cov*S) + D | |
669 if (kSA_GrBlendCoeff == fDstCoeff && srcAIsOne) { | |
670 return false; | |
671 } | |
672 | |
673 // We can always blend correctly if we have solid coverage. | |
674 if (coveragePOI.isSolidWhite()) { | |
675 return false; | |
676 } | |
677 | |
678 return true; | |
593 } | 679 } |
594 | 680 |
595 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); | 681 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); |
596 | 682 |
597 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, | 683 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, |
598 GrContext*, | 684 GrContext*, |
599 const GrDrawTargetCaps&, | 685 const GrDrawTargetCaps&, |
600 GrTexture*[]) { | 686 GrTexture*[]) { |
601 GrBlendCoeff src; | 687 GrBlendCoeff src; |
602 do { | 688 do { |
603 src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff)); | 689 src = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff)); |
604 } while (GrBlendCoeffRefsSrc(src)); | 690 } while (GrBlendCoeffRefsSrc(src)); |
605 | 691 |
606 GrBlendCoeff dst; | 692 GrBlendCoeff dst; |
607 do { | 693 do { |
608 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff)); | 694 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub licGrBlendCoeff)); |
609 } while (GrBlendCoeffRefsDst(dst)); | 695 } while (GrBlendCoeffRefsDst(dst)); |
610 | 696 |
611 return GrPorterDuffXPFactory::Create(src, dst); | 697 return GrPorterDuffXPFactory::Create(src, dst); |
612 } | 698 } |
613 | 699 |
OLD | NEW |