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 |
9 #include "GrDrawTargetCaps.h" | 10 #include "GrDrawTargetCaps.h" |
| 11 #include "GrRenderTarget.h" |
10 | 12 |
11 //////////////////////////////////////////////////////////////////////////////// | 13 //////////////////////////////////////////////////////////////////////////////// |
12 | 14 |
| 15 GrRODrawState::GrRODrawState(const GrRODrawState& drawState) : INHERITED() { |
| 16 fRenderTarget.setResource(SkSafeRef(drawState.fRenderTarget.getResource()), |
| 17 GrProgramResource::kWrite_IOType); |
| 18 } |
| 19 |
13 bool GrRODrawState::isEqual(const GrRODrawState& that) const { | 20 bool GrRODrawState::isEqual(const GrRODrawState& that) const { |
14 bool usingVertexColors = this->hasColorVertexAttribute(); | 21 bool usingVertexColors = this->hasColorVertexAttribute(); |
15 if (!usingVertexColors && this->fColor != that.fColor) { | 22 if (!usingVertexColors && this->fColor != that.fColor) { |
16 return false; | 23 return false; |
17 } | 24 } |
18 | 25 |
19 if (this->getRenderTarget() != that.getRenderTarget() || | 26 if (this->getRenderTarget() != that.getRenderTarget() || |
20 this->fColorStages.count() != that.fColorStages.count() || | 27 this->fColorStages.count() != that.fColorStages.count() || |
21 this->fCoverageStages.count() != that.fCoverageStages.count() || | 28 this->fCoverageStages.count() != that.fCoverageStages.count() || |
22 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) || | 29 !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) || |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 if (this->hasGeometryProcessor()) { | 164 if (this->hasGeometryProcessor()) { |
158 if (fGeometryProcessor->getEffect()->willReadDstColor()) { | 165 if (fGeometryProcessor->getEffect()->willReadDstColor()) { |
159 return true; | 166 return true; |
160 } | 167 } |
161 } | 168 } |
162 return false; | 169 return false; |
163 } | 170 } |
164 | 171 |
165 //////////////////////////////////////////////////////////////////////////////// | 172 //////////////////////////////////////////////////////////////////////////////// |
166 | 173 |
| 174 GrRODrawState::BlendOptFlags GrRODrawState::getBlendOpts(bool forceCoverage, |
| 175 GrBlendCoeff* srcCoeff, |
| 176 GrBlendCoeff* dstCoeff)
const { |
| 177 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff; |
| 178 if (NULL == srcCoeff) { |
| 179 srcCoeff = &bogusSrcCoeff; |
| 180 } |
| 181 if (NULL == dstCoeff) { |
| 182 dstCoeff = &bogusDstCoeff; |
| 183 } |
| 184 |
| 185 if (forceCoverage) { |
| 186 return this->calcBlendOpts(true, srcCoeff, dstCoeff); |
| 187 } |
| 188 |
| 189 if (0 == (fBlendOptFlags & kInvalid_BlendOptFlag)) { |
| 190 *srcCoeff = fOptSrcBlend; |
| 191 *dstCoeff = fOptDstBlend; |
| 192 return fBlendOptFlags; |
| 193 } |
| 194 |
| 195 fBlendOptFlags = this->calcBlendOpts(forceCoverage, srcCoeff, dstCoeff); |
| 196 fOptSrcBlend = *srcCoeff; |
| 197 fOptDstBlend = *dstCoeff; |
| 198 |
| 199 return fBlendOptFlags; |
| 200 } |
| 201 |
| 202 GrRODrawState::BlendOptFlags GrRODrawState::calcBlendOpts(bool forceCoverage, |
| 203 GrBlendCoeff* srcCoeff
, |
| 204 GrBlendCoeff* dstCoeff
) const { |
| 205 *srcCoeff = this->getSrcBlendCoeff(); |
| 206 *dstCoeff = this->getDstBlendCoeff(); |
| 207 |
| 208 if (this->isColorWriteDisabled()) { |
| 209 *srcCoeff = kZero_GrBlendCoeff; |
| 210 *dstCoeff = kOne_GrBlendCoeff; |
| 211 } |
| 212 |
| 213 bool srcAIsOne = this->srcAlphaWillBeOne(); |
| 214 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff || |
| 215 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne); |
| 216 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff || |
| 217 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne); |
| 218 |
| 219 // When coeffs are (0,1) there is no reason to draw at all, unless |
| 220 // stenciling is enabled. Having color writes disabled is effectively |
| 221 // (0,1). |
| 222 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) { |
| 223 if (this->getStencil().doesWrite()) { |
| 224 return kEmitCoverage_BlendOptFlag; |
| 225 } else { |
| 226 return kSkipDraw_BlendOptFlag; |
| 227 } |
| 228 } |
| 229 |
| 230 bool hasCoverage = forceCoverage || !this->hasSolidCoverage(); |
| 231 |
| 232 // if we don't have coverage we can check whether the dst |
| 233 // has to read at all. If not, we'll disable blending. |
| 234 if (!hasCoverage) { |
| 235 if (dstCoeffIsZero) { |
| 236 if (kOne_GrBlendCoeff == *srcCoeff) { |
| 237 // if there is no coverage and coeffs are (1,0) then we |
| 238 // won't need to read the dst at all, it gets replaced by src |
| 239 *dstCoeff = kZero_GrBlendCoeff; |
| 240 return kNone_BlendOpt; |
| 241 } else if (kZero_GrBlendCoeff == *srcCoeff) { |
| 242 // if the op is "clear" then we don't need to emit a color |
| 243 // or blend, just write transparent black into the dst. |
| 244 *srcCoeff = kOne_GrBlendCoeff; |
| 245 *dstCoeff = kZero_GrBlendCoeff; |
| 246 return kEmitTransBlack_BlendOptFlag; |
| 247 } |
| 248 } |
| 249 } else if (this->isCoverageDrawing()) { |
| 250 // we have coverage but we aren't distinguishing it from alpha by reques
t. |
| 251 return kCoverageAsAlpha_BlendOptFlag; |
| 252 } else { |
| 253 // check whether coverage can be safely rolled into alpha |
| 254 // of if we can skip color computation and just emit coverage |
| 255 if (this->canTweakAlphaForCoverage()) { |
| 256 return kCoverageAsAlpha_BlendOptFlag; |
| 257 } |
| 258 if (dstCoeffIsZero) { |
| 259 if (kZero_GrBlendCoeff == *srcCoeff) { |
| 260 // the source color is not included in the blend |
| 261 // the dst coeff is effectively zero so blend works out to: |
| 262 // (c)(0)D + (1-c)D = (1-c)D. |
| 263 *dstCoeff = kISA_GrBlendCoeff; |
| 264 return kEmitCoverage_BlendOptFlag; |
| 265 } else if (srcAIsOne) { |
| 266 // the dst coeff is effectively zero so blend works out to: |
| 267 // cS + (c)(0)D + (1-c)D = cS + (1-c)D. |
| 268 // If Sa is 1 then we can replace Sa with c |
| 269 // and set dst coeff to 1-Sa. |
| 270 *dstCoeff = kISA_GrBlendCoeff; |
| 271 return kCoverageAsAlpha_BlendOptFlag; |
| 272 } |
| 273 } else if (dstCoeffIsOne) { |
| 274 // the dst coeff is effectively one so blend works out to: |
| 275 // cS + (c)(1)D + (1-c)D = cS + D. |
| 276 *dstCoeff = kOne_GrBlendCoeff; |
| 277 return kCoverageAsAlpha_BlendOptFlag; |
| 278 } |
| 279 } |
| 280 |
| 281 return kNone_BlendOpt; |
| 282 } |
| 283 |
| 284 //////////////////////////////////////////////////////////////////////////////// |
| 285 |
167 // Some blend modes allow folding a fractional coverage value into the color's a
lpha channel, while | 286 // Some blend modes allow folding a fractional coverage value into the color's a
lpha channel, while |
168 // others will blend incorrectly. | 287 // others will blend incorrectly. |
169 bool GrRODrawState::canTweakAlphaForCoverage() const { | 288 bool GrRODrawState::canTweakAlphaForCoverage() const { |
170 /* | 289 /* |
171 The fractional coverage is f. | 290 The fractional coverage is f. |
172 The src and dst coeffs are Cs and Cd. | 291 The src and dst coeffs are Cs and Cd. |
173 The dst and src colors are S and D. | 292 The dst and src colors are S and D. |
174 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou
rce color's alpha | 293 We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the sou
rce color's alpha |
175 we're replacing S with S'=fS. It's obvious that that first term will always
be ok. The second | 294 we're replacing S with S'=fS. It's obvious that that first term will always
be ok. The second |
176 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss
ibilities for Cd we | 295 term can be rearranged as [1-(1-Cd)f]D. By substituting in the various poss
ibilities for Cd we |
(...skipping 13 matching lines...) Expand all Loading... |
190 for (int i = 0; i < fColorStages.count(); ++i) { | 309 for (int i = 0; i < fColorStages.count(); ++i) { |
191 fColorStages[i].convertToPendingExec(); | 310 fColorStages[i].convertToPendingExec(); |
192 } | 311 } |
193 if (fGeometryProcessor) { | 312 if (fGeometryProcessor) { |
194 fGeometryProcessor->convertToPendingExec(); | 313 fGeometryProcessor->convertToPendingExec(); |
195 } | 314 } |
196 for (int i = 0; i < fCoverageStages.count(); ++i) { | 315 for (int i = 0; i < fCoverageStages.count(); ++i) { |
197 fCoverageStages[i].convertToPendingExec(); | 316 fCoverageStages[i].convertToPendingExec(); |
198 } | 317 } |
199 } | 318 } |
| 319 |
| 320 bool GrRODrawState::srcAlphaWillBeOne() const { |
| 321 uint32_t validComponentFlags; |
| 322 GrColor color; |
| 323 // Check if per-vertex or constant color may have partial alpha |
| 324 if (this->hasColorVertexAttribute()) { |
| 325 if (fHints & kVertexColorsAreOpaque_Hint) { |
| 326 validComponentFlags = kA_GrColorComponentFlag; |
| 327 color = 0xFF << GrColor_SHIFT_A; |
| 328 } else { |
| 329 validComponentFlags = 0; |
| 330 color = 0; // not strictly necessary but we get false alarms from to
ols about uninit. |
| 331 } |
| 332 } else { |
| 333 validComponentFlags = kRGBA_GrColorComponentFlags; |
| 334 color = this->getColor(); |
| 335 } |
| 336 |
| 337 // Run through the color stages |
| 338 for (int s = 0; s < this->numColorStages(); ++s) { |
| 339 const GrEffect* effect = this->getColorStage(s).getEffect(); |
| 340 effect->getConstantColorComponents(&color, &validComponentFlags); |
| 341 } |
| 342 |
| 343 // Check whether coverage is treated as color. If so we run through the cove
rage computation. |
| 344 if (this->isCoverageDrawing()) { |
| 345 // The shader generated for coverage drawing runs the full coverage comp
utation and then |
| 346 // makes the shader output be the multiplication of color and coverage.
We mirror that here. |
| 347 GrColor coverage; |
| 348 uint32_t coverageComponentFlags; |
| 349 if (this->hasCoverageVertexAttribute()) { |
| 350 coverageComponentFlags = 0; |
| 351 coverage = 0; // suppresses any warnings. |
| 352 } else { |
| 353 coverageComponentFlags = kRGBA_GrColorComponentFlags; |
| 354 coverage = this->getCoverageColor(); |
| 355 } |
| 356 |
| 357 // Run through the coverage stages |
| 358 for (int s = 0; s < this->numCoverageStages(); ++s) { |
| 359 const GrEffect* effect = this->getCoverageStage(s).getEffect(); |
| 360 effect->getConstantColorComponents(&coverage, &coverageComponentFlag
s); |
| 361 } |
| 362 |
| 363 // Since the shader will multiply coverage and color, the only way the f
inal A==1 is if |
| 364 // coverage and color both have A==1. |
| 365 return (kA_GrColorComponentFlag & validComponentFlags & coverageComponen
tFlags) && |
| 366 0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage
); |
| 367 |
| 368 } |
| 369 |
| 370 return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnp
ackA(color); |
| 371 } |
| 372 |
| 373 //////////////////////////////////////////////////////////////////////////////// |
| 374 |
| 375 bool GrRODrawState::canIgnoreColorAttribute() const { |
| 376 if (fBlendOptFlags & kInvalid_BlendOptFlag) { |
| 377 this->getBlendOpts(); |
| 378 } |
| 379 return SkToBool(fBlendOptFlags & (GrRODrawState::kEmitTransBlack_BlendOptFla
g | |
| 380 GrRODrawState::kEmitCoverage_BlendOptFlag)
); |
| 381 } |
| 382 |
OLD | NEW |