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 "GrRODrawState.h" | 8 #include "GrRODrawState.h" |
9 #include "GrDrawTargetCaps.h" | 9 #include "GrDrawTargetCaps.h" |
10 | 10 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 for (int s = 0; s < this->numCoverageStages(); ++s) { | 138 for (int s = 0; s < this->numCoverageStages(); ++s) { |
139 if (this->getCoverageStage(s).getEffect()->willReadDstColor()) { | 139 if (this->getCoverageStage(s).getEffect()->willReadDstColor()) { |
140 return true; | 140 return true; |
141 } | 141 } |
142 } | 142 } |
143 return false; | 143 return false; |
144 } | 144 } |
145 | 145 |
146 //////////////////////////////////////////////////////////////////////////////// | 146 //////////////////////////////////////////////////////////////////////////////// |
147 | 147 |
| 148 GrRODrawState::BlendOptFlags GrRODrawState::getBlendOpts(bool forceCoverage, |
| 149 GrBlendCoeff* srcCoeff, |
| 150 GrBlendCoeff* dstCoeff)
const { |
| 151 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff; |
| 152 if (NULL == srcCoeff) { |
| 153 srcCoeff = &bogusSrcCoeff; |
| 154 } |
| 155 if (NULL == dstCoeff) { |
| 156 dstCoeff = &bogusDstCoeff; |
| 157 } |
| 158 |
| 159 if (forceCoverage) { |
| 160 return this->calcBlendOpts(true, srcCoeff, dstCoeff); |
| 161 } |
| 162 |
| 163 if (0 == (fBlendOptFlags & kInvalid_BlendOptFlag)) { |
| 164 *srcCoeff = fOptSrcBlend; |
| 165 *dstCoeff = fOptDstBlend; |
| 166 return fBlendOptFlags; |
| 167 } |
| 168 |
| 169 fBlendOptFlags = this->calcBlendOpts(forceCoverage, srcCoeff, dstCoeff); |
| 170 fOptSrcBlend = *srcCoeff; |
| 171 fOptDstBlend = *dstCoeff; |
| 172 |
| 173 return fBlendOptFlags; |
| 174 } |
| 175 |
| 176 GrRODrawState::BlendOptFlags GrRODrawState::calcBlendOpts(bool forceCoverage, |
| 177 GrBlendCoeff* srcCoeff
, |
| 178 GrBlendCoeff* dstCoeff
) const { |
| 179 *srcCoeff = this->getSrcBlendCoeff(); |
| 180 *dstCoeff = this->getDstBlendCoeff(); |
| 181 |
| 182 if (this->isColorWriteDisabled()) { |
| 183 *srcCoeff = kZero_GrBlendCoeff; |
| 184 *dstCoeff = kOne_GrBlendCoeff; |
| 185 } |
| 186 |
| 187 bool srcAIsOne = this->srcAlphaWillBeOne(); |
| 188 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff || |
| 189 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne); |
| 190 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff || |
| 191 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne); |
| 192 |
| 193 // When coeffs are (0,1) there is no reason to draw at all, unless |
| 194 // stenciling is enabled. Having color writes disabled is effectively |
| 195 // (0,1). |
| 196 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) { |
| 197 if (this->getStencil().doesWrite()) { |
| 198 return kEmitCoverage_BlendOptFlag; |
| 199 } else { |
| 200 return kSkipDraw_BlendOptFlag; |
| 201 } |
| 202 } |
| 203 |
| 204 bool hasCoverage = forceCoverage || !this->hasSolidCoverage(); |
| 205 |
| 206 // if we don't have coverage we can check whether the dst |
| 207 // has to read at all. If not, we'll disable blending. |
| 208 if (!hasCoverage) { |
| 209 if (dstCoeffIsZero) { |
| 210 if (kOne_GrBlendCoeff == *srcCoeff) { |
| 211 // if there is no coverage and coeffs are (1,0) then we |
| 212 // won't need to read the dst at all, it gets replaced by src |
| 213 *dstCoeff = kZero_GrBlendCoeff; |
| 214 return kNone_BlendOpt; |
| 215 } else if (kZero_GrBlendCoeff == *srcCoeff) { |
| 216 // if the op is "clear" then we don't need to emit a color |
| 217 // or blend, just write transparent black into the dst. |
| 218 *srcCoeff = kOne_GrBlendCoeff; |
| 219 *dstCoeff = kZero_GrBlendCoeff; |
| 220 return kEmitTransBlack_BlendOptFlag; |
| 221 } |
| 222 } |
| 223 } else if (this->isCoverageDrawing()) { |
| 224 // we have coverage but we aren't distinguishing it from alpha by reques
t. |
| 225 return kCoverageAsAlpha_BlendOptFlag; |
| 226 } else { |
| 227 // check whether coverage can be safely rolled into alpha |
| 228 // of if we can skip color computation and just emit coverage |
| 229 if (this->canTweakAlphaForCoverage()) { |
| 230 return kCoverageAsAlpha_BlendOptFlag; |
| 231 } |
| 232 if (dstCoeffIsZero) { |
| 233 if (kZero_GrBlendCoeff == *srcCoeff) { |
| 234 // the source color is not included in the blend |
| 235 // the dst coeff is effectively zero so blend works out to: |
| 236 // (c)(0)D + (1-c)D = (1-c)D. |
| 237 *dstCoeff = kISA_GrBlendCoeff; |
| 238 return kEmitCoverage_BlendOptFlag; |
| 239 } else if (srcAIsOne) { |
| 240 // the dst coeff is effectively zero so blend works out to: |
| 241 // cS + (c)(0)D + (1-c)D = cS + (1-c)D. |
| 242 // If Sa is 1 then we can replace Sa with c |
| 243 // and set dst coeff to 1-Sa. |
| 244 *dstCoeff = kISA_GrBlendCoeff; |
| 245 return kCoverageAsAlpha_BlendOptFlag; |
| 246 } |
| 247 } else if (dstCoeffIsOne) { |
| 248 // the dst coeff is effectively one so blend works out to: |
| 249 // cS + (c)(1)D + (1-c)D = cS + D. |
| 250 *dstCoeff = kOne_GrBlendCoeff; |
| 251 return kCoverageAsAlpha_BlendOptFlag; |
| 252 } |
| 253 } |
| 254 |
| 255 return kNone_BlendOpt; |
| 256 } |
| 257 |
| 258 //////////////////////////////////////////////////////////////////////////////// |
| 259 |
148 // Some blend modes allow folding a fractional coverage value into the color's a
lpha channel, while | 260 // Some blend modes allow folding a fractional coverage value into the color's a
lpha channel, while |
149 // others will blend incorrectly. | 261 // others will blend incorrectly. |
150 bool GrRODrawState::canTweakAlphaForCoverage() const { | 262 bool GrRODrawState::canTweakAlphaForCoverage() const { |
151 /* | 263 /* |
152 The fractional coverage is f. | 264 The fractional coverage is f. |
153 The src and dst coeffs are Cs and Cd. | 265 The src and dst coeffs are Cs and Cd. |
154 The dst and src colors are S and D. | 266 The dst and src colors are S and D. |
155 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou
rce color's alpha | 267 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou
rce color's alpha |
156 we're replacing S with S'=fS. It's obvious that that first term will always
be ok. The second | 268 we're replacing S with S'=fS. It's obvious that that first term will always
be ok. The second |
157 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss
ibilities for Cd we | 269 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss
ibilities for Cd we |
158 find that only 1, ISA, and ISC produce the correct destination when applied
to S' and D. | 270 find that only 1, ISA, and ISC produce the correct destination when applied
to S' and D. |
159 Also, if we're directly rendering coverage (isCoverageDrawing) then coverag
e is treated as | 271 Also, if we're directly rendering coverage (isCoverageDrawing) then coverag
e is treated as |
160 color by definition. | 272 color by definition. |
161 */ | 273 */ |
162 return kOne_GrBlendCoeff == fDstBlend || | 274 return kOne_GrBlendCoeff == fDstBlend || |
163 kISA_GrBlendCoeff == fDstBlend || | 275 kISA_GrBlendCoeff == fDstBlend || |
164 kISC_GrBlendCoeff == fDstBlend || | 276 kISC_GrBlendCoeff == fDstBlend || |
165 this->isCoverageDrawing(); | 277 this->isCoverageDrawing(); |
166 } | 278 } |
167 | 279 |
| 280 bool GrRODrawState::srcAlphaWillBeOne() const { |
| 281 uint32_t validComponentFlags; |
| 282 GrColor color; |
| 283 // Check if per-vertex or constant color may have partial alpha |
| 284 if (this->hasColorVertexAttribute()) { |
| 285 if (fHints & kVertexColorsAreOpaque_Hint) { |
| 286 validComponentFlags = kA_GrColorComponentFlag; |
| 287 color = 0xFF << GrColor_SHIFT_A; |
| 288 } else { |
| 289 validComponentFlags = 0; |
| 290 color = 0; // not strictly necessary but we get false alarms from to
ols about uninit. |
| 291 } |
| 292 } else { |
| 293 validComponentFlags = kRGBA_GrColorComponentFlags; |
| 294 color = this->getColor(); |
| 295 } |
| 296 |
| 297 // Run through the color stages |
| 298 for (int s = 0; s < this->numColorStages(); ++s) { |
| 299 const GrEffect* effect = this->getColorStage(s).getEffect(); |
| 300 effect->getConstantColorComponents(&color, &validComponentFlags); |
| 301 } |
| 302 |
| 303 // Check whether coverage is treated as color. If so we run through the cove
rage computation. |
| 304 if (this->isCoverageDrawing()) { |
| 305 // The shader generated for coverage drawing runs the full coverage comp
utation and then |
| 306 // makes the shader output be the multiplication of color and coverage.
We mirror that here. |
| 307 GrColor coverage; |
| 308 uint32_t coverageComponentFlags; |
| 309 if (this->hasCoverageVertexAttribute()) { |
| 310 coverageComponentFlags = 0; |
| 311 coverage = 0; // suppresses any warnings. |
| 312 } else { |
| 313 coverageComponentFlags = kRGBA_GrColorComponentFlags; |
| 314 coverage = this->getCoverageColor(); |
| 315 } |
| 316 |
| 317 // Run through the coverage stages |
| 318 for (int s = 0; s < this->numCoverageStages(); ++s) { |
| 319 const GrEffect* effect = this->getCoverageStage(s).getEffect(); |
| 320 effect->getConstantColorComponents(&coverage, &coverageComponentFlag
s); |
| 321 } |
| 322 |
| 323 // Since the shader will multiply coverage and color, the only way the f
inal A==1 is if |
| 324 // coverage and color both have A==1. |
| 325 return (kA_GrColorComponentFlag & validComponentFlags & coverageComponen
tFlags) && |
| 326 0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage
); |
| 327 |
| 328 } |
| 329 |
| 330 return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnp
ackA(color); |
| 331 } |
| 332 |
| 333 //////////////////////////////////////////////////////////////////////////////// |
| 334 |
| 335 bool GrRODrawState::canIgnoreColorAttribute() const { |
| 336 if (fBlendOptFlags & kInvalid_BlendOptFlag) { |
| 337 this->getBlendOpts(); |
| 338 } |
| 339 return SkToBool(fBlendOptFlags & (GrRODrawState::kEmitTransBlack_BlendOptFla
g | |
| 340 GrRODrawState::kEmitCoverage_BlendOptFlag)
); |
| 341 } |
| 342 |
OLD | NEW |