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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 case GrPorterDuffXferProcessor::kCoverageISC_SecondaryOutputType
: | 59 case GrPorterDuffXferProcessor::kCoverageISC_SecondaryOutputType
: |
60 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", | 60 fsBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", |
61 args.fOutputSecondary, args.fInputCol
or, | 61 args.fOutputSecondary, args.fInputCol
or, |
62 args.fInputCoverage); | 62 args.fInputCoverage); |
63 break; | 63 break; |
64 default: | 64 default: |
65 SkFAIL("Unexpected Secondary Output"); | 65 SkFAIL("Unexpected Secondary Output"); |
66 } | 66 } |
67 } | 67 } |
68 | 68 |
69 fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInput
Color, | 69 switch (xp.primaryOutputType()) { |
70 args.fInputCoverage); | 70 case GrPorterDuffXferProcessor::kNone_PrimaryOutputType: |
71 if (GrPorterDuffXferProcessor::kCombineWithDst_PrimaryOutputType == xp.p
rimaryOutputType()){ | 71 fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary); |
72 fsBuilder->codeAppendf("%s += (vec4(1.0) - %s) * %s;", args.fOutputP
rimary, | 72 break; |
73 args.fInputCoverage, fsBuilder->dstColor()); | 73 case GrPorterDuffXferProcessor::kColor_PrimaryOutputType: |
| 74 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fIn
putColor); |
| 75 break; |
| 76 case GrPorterDuffXferProcessor::kCoverage_PrimaryOutputType: |
| 77 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fIn
putCoverage); |
| 78 break; |
| 79 case GrPorterDuffXferProcessor::kModulate_PrimaryOutputType: |
| 80 case GrPorterDuffXferProcessor::kCombineWithDst_PrimaryOutputType: |
| 81 fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, arg
s.fInputColor, |
| 82 args.fInputCoverage); |
| 83 if (GrPorterDuffXferProcessor::kCombineWithDst_PrimaryOutputType
== |
| 84 xp.primaryOutputType()){ |
| 85 fsBuilder->codeAppendf("%s += (vec4(1.0) - %s) * %s;", args.
fOutputPrimary, |
| 86 args.fInputCoverage, fsBuilder->dstCo
lor()); |
| 87 } |
| 88 break; |
| 89 default: |
| 90 SkFAIL("Unexpected Primary Output"); |
74 } | 91 } |
75 } | 92 } |
76 | 93 |
77 virtual void setData(const GrGLProgramDataManager&, const GrXferProcessor&)
SK_OVERRIDE {}; | 94 virtual void setData(const GrGLProgramDataManager&, const GrXferProcessor&)
SK_OVERRIDE {}; |
78 | 95 |
79 static void GenKey(const GrProcessor& processor, const GrGLCaps& caps, | 96 static void GenKey(const GrProcessor& processor, const GrGLCaps& caps, |
80 GrProcessorKeyBuilder* b) { | 97 GrProcessorKeyBuilder* b) { |
81 const GrPorterDuffXferProcessor& xp = processor.cast<GrPorterDuffXferPro
cessor>(); | 98 const GrPorterDuffXferProcessor& xp = processor.cast<GrPorterDuffXferPro
cessor>(); |
82 b->add32(xp.primaryOutputType()); | 99 b->add32(xp.primaryOutputType()); |
83 b->add32(xp.secondaryOutputType()); | 100 b->add32(xp.secondaryOutputType()); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | 132 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
116 } | 133 } |
117 | 134 |
118 GrXferProcessor::OptFlags | 135 GrXferProcessor::OptFlags |
119 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, | 136 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, |
120 const GrProcOptInfo& coveragePOI, | 137 const GrProcOptInfo& coveragePOI, |
121 bool isCoverageDrawing, | 138 bool isCoverageDrawing, |
122 bool colorWriteDisabled, | 139 bool colorWriteDisabled, |
123 bool doesStencilWrite, | 140 bool doesStencilWrite, |
124 GrColor* overrideColor, | 141 GrColor* overrideColor, |
125 uint8_t* overrideCoverage, | |
126 const GrDrawTargetCaps& caps) { | 142 const GrDrawTargetCaps& caps) { |
127 GrXferProcessor::OptFlags optFlags; | 143 GrXferProcessor::OptFlags optFlags; |
128 // Optimizations when doing RGB Coverage | 144 // Optimizations when doing RGB Coverage |
129 if (coveragePOI.isFourChannelOutput()) { | 145 if (coveragePOI.isFourChannelOutput()) { |
130 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha | 146 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha |
131 // value of the blend the constant. We should already have valid blend c
oeff's if we are at | 147 // value of the blend the constant. We should already have valid blend c
oeff's if we are at |
132 // a point where we have RGB coverage. We don't need any color stages si
nce the known color | 148 // a point where we have RGB coverage. We don't need any color stages si
nce the known color |
133 // output is already baked into the blendConstant. | 149 // output is already baked into the blendConstant. |
134 uint8_t alpha = GrColorUnpackA(fBlendConstant); | 150 uint8_t alpha = GrColorUnpackA(fBlendConstant); |
135 *overrideColor = GrColorPackRGBA(alpha, alpha, alpha, alpha); | 151 *overrideColor = GrColorPackRGBA(alpha, alpha, alpha, alpha); |
136 optFlags = GrXferProcessor::kOverrideColor_OptFlag; | 152 optFlags = GrXferProcessor::kOverrideColor_OptFlag; |
137 } else { | 153 } else { |
138 optFlags = this->internalGetOptimizations(colorPOI, | 154 optFlags = this->internalGetOptimizations(colorPOI, |
139 coveragePOI, | 155 coveragePOI, |
140 isCoverageDrawing, | 156 isCoverageDrawing, |
141 colorWriteDisabled, | 157 colorWriteDisabled, |
142 doesStencilWrite, | 158 doesStencilWrite); |
143 overrideColor, | |
144 overrideCoverage); | |
145 } | 159 } |
146 this->calcOutputTypes(optFlags, caps, isCoverageDrawing || coveragePOI.isSol
idWhite(), | 160 this->calcOutputTypes(optFlags, caps, isCoverageDrawing || coveragePOI.isSol
idWhite(), |
147 colorPOI.readsDst() || coveragePOI.readsDst()); | 161 colorPOI.readsDst() || coveragePOI.readsDst()); |
148 return optFlags; | 162 return optFlags; |
149 } | 163 } |
150 | 164 |
151 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla
gs, | 165 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla
gs, |
152 const GrDrawTargetCaps& caps, | 166 const GrDrawTargetCaps& caps, |
153 bool hasSolidCoverage, bool read
sDst) { | 167 bool hasSolidCoverage, bool read
sDst) { |
| 168 if (optFlags & kIgnoreColor_OptFlag) { |
| 169 if (optFlags & kIgnoreCoverage_OptFlag) { |
| 170 fPrimaryOutputType = kNone_PrimaryOutputType; |
| 171 return; |
| 172 } else { |
| 173 fPrimaryOutputType = kCoverage_PrimaryOutputType; |
| 174 return; |
| 175 } |
| 176 } else if (optFlags & kIgnoreCoverage_OptFlag) { |
| 177 fPrimaryOutputType = kColor_PrimaryOutputType; |
| 178 return; |
| 179 } |
| 180 |
154 // If we do have coverage determine whether it matters. Dual source blendin
g is expensive so | 181 // If we do have coverage determine whether it matters. Dual source blendin
g is expensive so |
155 // we don't do it if we are doing coverage drawing. If we aren't then We al
ways do dual source | 182 // we don't do it if we are doing coverage drawing. If we aren't then We al
ways do dual source |
156 // blending if we have any effective coverage stages OR the geometry process
or doesn't emits | 183 // blending if we have any effective coverage stages OR the geometry process
or doesn't emits |
157 // solid coverage. | 184 // solid coverage. |
158 if (!(optFlags & kSetCoverageDrawing_OptFlag) && !hasSolidCoverage) { | 185 if (!(optFlags & kSetCoverageDrawing_OptFlag) && !hasSolidCoverage) { |
159 if (caps.dualSourceBlendingSupport()) { | 186 if (caps.dualSourceBlendingSupport()) { |
160 if (kZero_GrBlendCoeff == fDstBlend) { | 187 if (kZero_GrBlendCoeff == fDstBlend) { |
161 // write the coverage value to second color | 188 // write the coverage value to second color |
162 fSecondaryOutputType = kCoverage_SecondaryOutputType; | 189 fSecondaryOutputType = kCoverage_SecondaryOutputType; |
163 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; | 190 fDstBlend = (GrBlendCoeff)GrGpu::kIS2C_GrBlendCoeff; |
(...skipping 12 matching lines...) Expand all Loading... |
176 fPrimaryOutputType = kCombineWithDst_PrimaryOutputType; | 203 fPrimaryOutputType = kCombineWithDst_PrimaryOutputType; |
177 } | 204 } |
178 } | 205 } |
179 } | 206 } |
180 | 207 |
181 GrXferProcessor::OptFlags | 208 GrXferProcessor::OptFlags |
182 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
I, | 209 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
I, |
183 const GrProcOptInfo& coverag
ePOI, | 210 const GrProcOptInfo& coverag
ePOI, |
184 bool isCoverageDrawing, | 211 bool isCoverageDrawing, |
185 bool colorWriteDisabled, | 212 bool colorWriteDisabled, |
186 bool doesStencilWrite, | 213 bool doesStencilWrite) { |
187 GrColor* overrideColor, | |
188 uint8_t* overrideCoverage) { | |
189 if (colorWriteDisabled) { | 214 if (colorWriteDisabled) { |
190 fSrcBlend = kZero_GrBlendCoeff; | 215 fSrcBlend = kZero_GrBlendCoeff; |
191 fDstBlend = kOne_GrBlendCoeff; | 216 fDstBlend = kOne_GrBlendCoeff; |
192 } | 217 } |
193 | 218 |
194 bool srcAIsOne; | 219 bool srcAIsOne; |
195 bool hasCoverage; | 220 bool hasCoverage; |
196 if (isCoverageDrawing) { | 221 if (isCoverageDrawing) { |
197 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque(); | 222 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque(); |
198 hasCoverage = false; | 223 hasCoverage = false; |
199 } else { | 224 } else { |
200 srcAIsOne = colorPOI.isOpaque(); | 225 srcAIsOne = colorPOI.isOpaque(); |
201 hasCoverage = !coveragePOI.isSolidWhite(); | 226 hasCoverage = !coveragePOI.isSolidWhite(); |
202 } | 227 } |
203 | 228 |
204 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || | 229 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || |
205 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); | 230 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); |
206 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || | 231 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || |
207 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); | 232 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); |
208 | 233 |
209 // When coeffs are (0,1) there is no reason to draw at all, unless | 234 // When coeffs are (0,1) there is no reason to draw at all, unless |
210 // stenciling is enabled. Having color writes disabled is effectively | 235 // stenciling is enabled. Having color writes disabled is effectively |
211 // (0,1). | 236 // (0,1). |
212 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { | 237 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { |
213 if (doesStencilWrite) { | 238 if (doesStencilWrite) { |
214 *overrideColor = 0xffffffff; | 239 return GrXferProcessor::kIgnoreColor_OptFlag | |
215 return GrXferProcessor::kClearColorStages_OptFlag | | |
216 GrXferProcessor::kSetCoverageDrawing_OptFlag; | 240 GrXferProcessor::kSetCoverageDrawing_OptFlag; |
217 } else { | 241 } else { |
218 fDstBlend = kOne_GrBlendCoeff; | 242 fDstBlend = kOne_GrBlendCoeff; |
219 return GrXferProcessor::kSkipDraw_OptFlag; | 243 return GrXferProcessor::kSkipDraw_OptFlag; |
220 } | 244 } |
221 } | 245 } |
222 | 246 |
223 // if we don't have coverage we can check whether the dst | 247 // if we don't have coverage we can check whether the dst |
224 // has to read at all. If not, we'll disable blending. | 248 // has to read at all. If not, we'll disable blending. |
225 if (!hasCoverage) { | 249 if (!hasCoverage) { |
226 if (dstCoeffIsZero) { | 250 if (dstCoeffIsZero) { |
227 if (kOne_GrBlendCoeff == fSrcBlend) { | 251 if (kOne_GrBlendCoeff == fSrcBlend) { |
228 // if there is no coverage and coeffs are (1,0) then we | 252 // if there is no coverage and coeffs are (1,0) then we |
229 // won't need to read the dst at all, it gets replaced by src | 253 // won't need to read the dst at all, it gets replaced by src |
230 fDstBlend = kZero_GrBlendCoeff; | 254 fDstBlend = kZero_GrBlendCoeff; |
231 return GrXferProcessor::kNone_Opt; | 255 return GrXferProcessor::kNone_Opt; |
232 } else if (kZero_GrBlendCoeff == fSrcBlend) { | 256 } else if (kZero_GrBlendCoeff == fSrcBlend) { |
233 // if the op is "clear" then we don't need to emit a color | 257 // if the op is "clear" then we don't need to emit a color |
234 // or blend, just write transparent black into the dst. | 258 // or blend, just write transparent black into the dst. |
235 fSrcBlend = kOne_GrBlendCoeff; | 259 fSrcBlend = kOne_GrBlendCoeff; |
236 fDstBlend = kZero_GrBlendCoeff; | 260 fDstBlend = kZero_GrBlendCoeff; |
237 *overrideColor = 0; | 261 return GrXferProcessor::kIgnoreColor_OptFlag | |
238 *overrideCoverage = 0xff; | 262 GrXferProcessor::kIgnoreCoverage_OptFlag; |
239 return GrXferProcessor::kClearColorStages_OptFlag | | |
240 GrXferProcessor::kClearCoverageStages_OptFlag; | |
241 } | 263 } |
242 } | 264 } |
243 } else if (isCoverageDrawing) { | 265 } else if (isCoverageDrawing) { |
244 // we have coverage but we aren't distinguishing it from alpha by reques
t. | 266 // we have coverage but we aren't distinguishing it from alpha by reques
t. |
245 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 267 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
246 } else { | 268 } else { |
247 // check whether coverage can be safely rolled into alpha | 269 // check whether coverage can be safely rolled into alpha |
248 // of if we can skip color computation and just emit coverage | 270 // of if we can skip color computation and just emit coverage |
249 if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) { | 271 if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) { |
250 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 272 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
251 } | 273 } |
252 if (dstCoeffIsZero) { | 274 if (dstCoeffIsZero) { |
253 if (kZero_GrBlendCoeff == fSrcBlend) { | 275 if (kZero_GrBlendCoeff == fSrcBlend) { |
254 // the source color is not included in the blend | 276 // the source color is not included in the blend |
255 // the dst coeff is effectively zero so blend works out to: | 277 // the dst coeff is effectively zero so blend works out to: |
256 // (c)(0)D + (1-c)D = (1-c)D. | 278 // (c)(0)D + (1-c)D = (1-c)D. |
257 fDstBlend = kISA_GrBlendCoeff; | 279 fDstBlend = kISA_GrBlendCoeff; |
258 *overrideColor = 0xffffffff; | 280 return GrXferProcessor::kIgnoreColor_OptFlag | |
259 return GrXferProcessor::kClearColorStages_OptFlag | | |
260 GrXferProcessor::kSetCoverageDrawing_OptFlag; | 281 GrXferProcessor::kSetCoverageDrawing_OptFlag; |
261 } else if (srcAIsOne) { | 282 } else if (srcAIsOne) { |
262 // the dst coeff is effectively zero so blend works out to: | 283 // the dst coeff is effectively zero so blend works out to: |
263 // cS + (c)(0)D + (1-c)D = cS + (1-c)D. | 284 // cS + (c)(0)D + (1-c)D = cS + (1-c)D. |
264 // If Sa is 1 then we can replace Sa with c | 285 // If Sa is 1 then we can replace Sa with c |
265 // and set dst coeff to 1-Sa. | 286 // and set dst coeff to 1-Sa. |
266 fDstBlend = kISA_GrBlendCoeff; | 287 fDstBlend = kISA_GrBlendCoeff; |
267 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 288 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
268 } | 289 } |
269 } else if (dstCoeffIsOne) { | 290 } else if (dstCoeffIsOne) { |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 } while (GrBlendCoeffRefsSrc(src)); | 572 } while (GrBlendCoeffRefsSrc(src)); |
552 | 573 |
553 GrBlendCoeff dst; | 574 GrBlendCoeff dst; |
554 do { | 575 do { |
555 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub
licGrBlendCoeff)); | 576 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub
licGrBlendCoeff)); |
556 } while (GrBlendCoeffRefsDst(dst)); | 577 } while (GrBlendCoeffRefsDst(dst)); |
557 | 578 |
558 return GrPorterDuffXPFactory::Create(src, dst); | 579 return GrPorterDuffXPFactory::Create(src, dst); |
559 } | 580 } |
560 | 581 |
OLD | NEW |