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