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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou
t) const { | 114 void GrPorterDuffXferProcessor::onComputeInvariantOutput(GrInvariantOutput* inou
t) const { |
115 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); | 115 inout->setToUnknown(GrInvariantOutput::kWill_ReadInput); |
116 } | 116 } |
117 | 117 |
118 GrXferProcessor::OptFlags | 118 GrXferProcessor::OptFlags |
119 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, | 119 GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI, |
120 const GrProcOptInfo& coveragePOI, | 120 const GrProcOptInfo& coveragePOI, |
121 bool isCoverageDrawing, | 121 bool isCoverageDrawing, |
122 bool colorWriteDisabled, | 122 bool colorWriteDisabled, |
123 bool doesStencilWrite, | 123 bool doesStencilWrite, |
124 GrColor* color, uint8_t* coverage, | 124 GrColor* overrideColor, |
| 125 uint8_t* overrideCoverage, |
125 const GrDrawTargetCaps& caps) { | 126 const GrDrawTargetCaps& caps) { |
126 GrXferProcessor::OptFlags optFlags = this->internalGetOptimizations(colorPOI
, | 127 GrXferProcessor::OptFlags optFlags; |
127 coverage
POI, | 128 // Optimizations when doing RGB Coverage |
128 isCovera
geDrawing, | 129 if (coveragePOI.isFourChannelOutput()) { |
129 colorWri
teDisabled, | 130 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha |
130 doesSten
cilWrite, | 131 // value of the blend the constant. We should already have valid blend c
oeff's if we are at |
131 color, | 132 // a point where we have RGB coverage. We don't need any color stages si
nce the known color |
132 coverage
); | 133 // output is already baked into the blendConstant. |
133 | 134 uint8_t alpha = GrColorUnpackA(fBlendConstant); |
| 135 *overrideColor = GrColorPackRGBA(alpha, alpha, alpha, alpha); |
| 136 optFlags = GrXferProcessor::kOverrideColor_OptFlag; |
| 137 } else { |
| 138 optFlags = this->internalGetOptimizations(colorPOI, |
| 139 coveragePOI, |
| 140 isCoverageDrawing, |
| 141 colorWriteDisabled, |
| 142 doesStencilWrite, |
| 143 overrideColor, |
| 144 overrideCoverage); |
| 145 } |
134 this->calcOutputTypes(optFlags, caps, isCoverageDrawing || coveragePOI.isSol
idWhite(), | 146 this->calcOutputTypes(optFlags, caps, isCoverageDrawing || coveragePOI.isSol
idWhite(), |
135 colorPOI.readsDst() || coveragePOI.readsDst()); | 147 colorPOI.readsDst() || coveragePOI.readsDst()); |
136 return optFlags; | 148 return optFlags; |
137 } | 149 } |
138 | 150 |
139 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla
gs, | 151 void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFla
gs, |
140 const GrDrawTargetCaps& caps, | 152 const GrDrawTargetCaps& caps, |
141 bool hasSolidCoverage, bool read
sDst) { | 153 bool hasSolidCoverage, bool read
sDst) { |
142 // If we do have coverage determine whether it matters. Dual source blendin
g is expensive so | 154 // If we do have coverage determine whether it matters. Dual source blendin
g is expensive so |
143 // we don't do it if we are doing coverage drawing. If we aren't then We al
ways do dual source | 155 // we don't do it if we are doing coverage drawing. If we aren't then We al
ways do dual source |
(...skipping 21 matching lines...) Expand all Loading... |
165 } | 177 } |
166 } | 178 } |
167 } | 179 } |
168 | 180 |
169 GrXferProcessor::OptFlags | 181 GrXferProcessor::OptFlags |
170 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
I, | 182 GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
I, |
171 const GrProcOptInfo& coverag
ePOI, | 183 const GrProcOptInfo& coverag
ePOI, |
172 bool isCoverageDrawing, | 184 bool isCoverageDrawing, |
173 bool colorWriteDisabled, | 185 bool colorWriteDisabled, |
174 bool doesStencilWrite, | 186 bool doesStencilWrite, |
175 GrColor* color, uint8_t* cov
erage) { | 187 GrColor* overrideColor, |
| 188 uint8_t* overrideCoverage) { |
176 if (colorWriteDisabled) { | 189 if (colorWriteDisabled) { |
177 fSrcBlend = kZero_GrBlendCoeff; | 190 fSrcBlend = kZero_GrBlendCoeff; |
178 fDstBlend = kOne_GrBlendCoeff; | 191 fDstBlend = kOne_GrBlendCoeff; |
179 } | 192 } |
180 | 193 |
181 bool srcAIsOne; | 194 bool srcAIsOne; |
182 bool hasCoverage; | 195 bool hasCoverage; |
183 if (isCoverageDrawing) { | 196 if (isCoverageDrawing) { |
184 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque(); | 197 srcAIsOne = colorPOI.isOpaque() && coveragePOI.isOpaque(); |
185 hasCoverage = false; | 198 hasCoverage = false; |
186 } else { | 199 } else { |
187 srcAIsOne = colorPOI.isOpaque(); | 200 srcAIsOne = colorPOI.isOpaque(); |
188 hasCoverage = !coveragePOI.isSolidWhite(); | 201 hasCoverage = !coveragePOI.isSolidWhite(); |
189 } | 202 } |
190 | 203 |
191 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || | 204 bool dstCoeffIsOne = kOne_GrBlendCoeff == fDstBlend || |
192 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); | 205 (kSA_GrBlendCoeff == fDstBlend && srcAIsOne); |
193 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || | 206 bool dstCoeffIsZero = kZero_GrBlendCoeff == fDstBlend || |
194 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); | 207 (kISA_GrBlendCoeff == fDstBlend && srcAIsOne); |
195 | 208 |
196 // Optimizations when doing RGB Coverage | |
197 if (coveragePOI.isFourChannelOutput()) { | |
198 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha | |
199 // value of the blend the constant. We should already have valid blend c
oeff's if we are at | |
200 // a point where we have RGB coverage. We don't need any color stages si
nce the known color | |
201 // output is already baked into the blendConstant. | |
202 uint8_t alpha = GrColorUnpackA(fBlendConstant); | |
203 *color = GrColorPackRGBA(alpha, alpha, alpha, alpha); | |
204 return GrXferProcessor::kClearColorStages_OptFlag; | |
205 } | |
206 | |
207 // When coeffs are (0,1) there is no reason to draw at all, unless | 209 // When coeffs are (0,1) there is no reason to draw at all, unless |
208 // stenciling is enabled. Having color writes disabled is effectively | 210 // stenciling is enabled. Having color writes disabled is effectively |
209 // (0,1). | 211 // (0,1). |
210 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { | 212 if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) { |
211 if (doesStencilWrite) { | 213 if (doesStencilWrite) { |
212 *color = 0xffffffff; | 214 *overrideColor = 0xffffffff; |
213 return GrXferProcessor::kClearColorStages_OptFlag | | 215 return GrXferProcessor::kClearColorStages_OptFlag | |
214 GrXferProcessor::kSetCoverageDrawing_OptFlag; | 216 GrXferProcessor::kSetCoverageDrawing_OptFlag; |
215 } else { | 217 } else { |
216 fDstBlend = kOne_GrBlendCoeff; | 218 fDstBlend = kOne_GrBlendCoeff; |
217 return GrXferProcessor::kSkipDraw_OptFlag; | 219 return GrXferProcessor::kSkipDraw_OptFlag; |
218 } | 220 } |
219 } | 221 } |
220 | 222 |
221 // if we don't have coverage we can check whether the dst | 223 // if we don't have coverage we can check whether the dst |
222 // has to read at all. If not, we'll disable blending. | 224 // has to read at all. If not, we'll disable blending. |
223 if (!hasCoverage) { | 225 if (!hasCoverage) { |
224 if (dstCoeffIsZero) { | 226 if (dstCoeffIsZero) { |
225 if (kOne_GrBlendCoeff == fSrcBlend) { | 227 if (kOne_GrBlendCoeff == fSrcBlend) { |
226 // if there is no coverage and coeffs are (1,0) then we | 228 // if there is no coverage and coeffs are (1,0) then we |
227 // won't need to read the dst at all, it gets replaced by src | 229 // won't need to read the dst at all, it gets replaced by src |
228 fDstBlend = kZero_GrBlendCoeff; | 230 fDstBlend = kZero_GrBlendCoeff; |
229 return GrXferProcessor::kNone_Opt; | 231 return GrXferProcessor::kNone_Opt; |
230 } else if (kZero_GrBlendCoeff == fSrcBlend) { | 232 } else if (kZero_GrBlendCoeff == fSrcBlend) { |
231 // if the op is "clear" then we don't need to emit a color | 233 // if the op is "clear" then we don't need to emit a color |
232 // or blend, just write transparent black into the dst. | 234 // or blend, just write transparent black into the dst. |
233 fSrcBlend = kOne_GrBlendCoeff; | 235 fSrcBlend = kOne_GrBlendCoeff; |
234 fDstBlend = kZero_GrBlendCoeff; | 236 fDstBlend = kZero_GrBlendCoeff; |
235 *color = 0; | 237 *overrideColor = 0; |
236 *coverage = 0xff; | 238 *overrideCoverage = 0xff; |
237 return GrXferProcessor::kClearColorStages_OptFlag | | 239 return GrXferProcessor::kClearColorStages_OptFlag | |
238 GrXferProcessor::kClearCoverageStages_OptFlag; | 240 GrXferProcessor::kClearCoverageStages_OptFlag; |
239 } | 241 } |
240 } | 242 } |
241 } else if (isCoverageDrawing) { | 243 } else if (isCoverageDrawing) { |
242 // we have coverage but we aren't distinguishing it from alpha by reques
t. | 244 // we have coverage but we aren't distinguishing it from alpha by reques
t. |
243 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 245 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
244 } else { | 246 } else { |
245 // check whether coverage can be safely rolled into alpha | 247 // check whether coverage can be safely rolled into alpha |
246 // of if we can skip color computation and just emit coverage | 248 // of if we can skip color computation and just emit coverage |
247 if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) { | 249 if (can_tweak_alpha_for_coverage(fDstBlend, isCoverageDrawing)) { |
248 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 250 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
249 } | 251 } |
250 if (dstCoeffIsZero) { | 252 if (dstCoeffIsZero) { |
251 if (kZero_GrBlendCoeff == fSrcBlend) { | 253 if (kZero_GrBlendCoeff == fSrcBlend) { |
252 // the source color is not included in the blend | 254 // the source color is not included in the blend |
253 // the dst coeff is effectively zero so blend works out to: | 255 // the dst coeff is effectively zero so blend works out to: |
254 // (c)(0)D + (1-c)D = (1-c)D. | 256 // (c)(0)D + (1-c)D = (1-c)D. |
255 fDstBlend = kISA_GrBlendCoeff; | 257 fDstBlend = kISA_GrBlendCoeff; |
256 *color = 0xffffffff; | 258 *overrideColor = 0xffffffff; |
257 return GrXferProcessor::kClearColorStages_OptFlag | | 259 return GrXferProcessor::kClearColorStages_OptFlag | |
258 GrXferProcessor::kSetCoverageDrawing_OptFlag; | 260 GrXferProcessor::kSetCoverageDrawing_OptFlag; |
259 } else if (srcAIsOne) { | 261 } else if (srcAIsOne) { |
260 // the dst coeff is effectively zero so blend works out to: | 262 // the dst coeff is effectively zero so blend works out to: |
261 // cS + (c)(0)D + (1-c)D = cS + (1-c)D. | 263 // cS + (c)(0)D + (1-c)D = cS + (1-c)D. |
262 // If Sa is 1 then we can replace Sa with c | 264 // If Sa is 1 then we can replace Sa with c |
263 // and set dst coeff to 1-Sa. | 265 // and set dst coeff to 1-Sa. |
264 fDstBlend = kISA_GrBlendCoeff; | 266 fDstBlend = kISA_GrBlendCoeff; |
265 return GrXferProcessor::kSetCoverageDrawing_OptFlag; | 267 return GrXferProcessor::kSetCoverageDrawing_OptFlag; |
266 } | 268 } |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 } while (GrBlendCoeffRefsSrc(src)); | 551 } while (GrBlendCoeffRefsSrc(src)); |
550 | 552 |
551 GrBlendCoeff dst; | 553 GrBlendCoeff dst; |
552 do { | 554 do { |
553 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub
licGrBlendCoeff)); | 555 dst = GrBlendCoeff(random->nextRangeU(kFirstPublicGrBlendCoeff, kLastPub
licGrBlendCoeff)); |
554 } while (GrBlendCoeffRefsDst(dst)); | 556 } while (GrBlendCoeffRefsDst(dst)); |
555 | 557 |
556 return GrPorterDuffXPFactory::Create(src, dst); | 558 return GrPorterDuffXPFactory::Create(src, dst); |
557 } | 559 } |
558 | 560 |
OLD | NEW |