| Index: src/gpu/GrDrawState.cpp
|
| diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
|
| index a0dc426d7056c4e41dfd2c85bb1e865e8c6c4333..d54d085d0ed24b74566e8e081e74d77a3b90ddb1 100644
|
| --- a/src/gpu/GrDrawState.cpp
|
| +++ b/src/gpu/GrDrawState.cpp
|
| @@ -7,6 +7,7 @@
|
|
|
| #include "GrDrawState.h"
|
| #include "GrPaint.h"
|
| +#include "GrDrawTargetCaps.h"
|
|
|
| //////////////////////////////////////////////////////////////////////////////s
|
|
|
| @@ -34,7 +35,7 @@ bool GrDrawState::State::HaveCompatibleState(const State& a, const State& b,
|
| }
|
| //////////////////////////////////////////////////////////////////////////////s
|
| GrDrawState::CombinedState GrDrawState::CombineIfPossible(
|
| - const GrDrawState& a, const GrDrawState& b) {
|
| + const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
|
|
|
| bool usingVertexColors = a.hasColorVertexAttribute();
|
| if (!usingVertexColors && a.fColor != b.fColor) {
|
| @@ -65,10 +66,35 @@ GrDrawState::CombinedState GrDrawState::CombineIfPossible(
|
| if (!State::HaveCompatibleState(a.fState, b.fState, explicitLocalCoords)) {
|
| return kIncompatible_CombinedState;
|
| }
|
| +
|
| + if (usingVertexColors) {
|
| + // If one is opaque and the other is not then the combined state is not opaque. Moreover,
|
| + // if the opaqueness affects the ability to get color/coverage blending correct then we
|
| + // don't combine the draw states.
|
| + bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
|
| + bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
|
| + if (aIsOpaque != bIsOpaque) {
|
| + const GrDrawState* opaque;
|
| + const GrDrawState* nonOpaque;
|
| + if (aIsOpaque) {
|
| + opaque = &a;
|
| + nonOpaque = &b;
|
| + } else {
|
| + opaque = &b;
|
| + nonOpaque = &a;
|
| + }
|
| + if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
|
| + SkASSERT(!nonOpaque->hasSolidCoverage());
|
| + if (!nonOpaque->couldApplyCoverage(caps)) {
|
| + return kIncompatible_CombinedState;
|
| + }
|
| + }
|
| + return aIsOpaque ? kB_CombinedState : kA_CombinedState;
|
| + }
|
| + }
|
| return kAOrB_CombinedState;
|
| }
|
|
|
| -
|
| //////////////////////////////////////////////////////////////////////////////s
|
|
|
| GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
|
| @@ -102,6 +128,7 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
|
| fBlendOptFlags = that.fBlendOptFlags;
|
|
|
| fState = that.fState;
|
| + fHints = that.fHints;
|
|
|
| memcpy(fFixedFunctionVertexAttribIndices,
|
| that.fFixedFunctionVertexAttribIndices,
|
| @@ -129,6 +156,8 @@ void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
|
| fCoverage = 0xffffffff;
|
| fDrawFace = kBoth_DrawFace;
|
|
|
| + fHints = 0;
|
| +
|
| this->invalidateBlendOptFlags();
|
| }
|
|
|
| @@ -172,6 +201,7 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende
|
| fDrawFace = kBoth_DrawFace;
|
| fStencilSettings.setDisabled();
|
| this->resetStateFlags();
|
| + fHints = 0;
|
|
|
| // Enable the clip bit
|
| this->enableState(GrDrawState::kClip_StateBit);
|
| @@ -326,13 +356,33 @@ bool GrDrawState::willEffectReadDstColor() const {
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
|
|
| +bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
|
| + if (caps.dualSourceBlendingSupport()) {
|
| + return true;
|
| + }
|
| + // we can correctly apply coverage if a) we have dual source blending
|
| + // or b) one of our blend optimizations applies
|
| + // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
|
| + GrBlendCoeff srcCoeff;
|
| + GrBlendCoeff dstCoeff;
|
| + GrDrawState::BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
|
| + return GrDrawState::kNone_BlendOpt != flag ||
|
| + (this->willEffectReadDstColor() &&
|
| + kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
|
| +}
|
| +
|
| bool GrDrawState::srcAlphaWillBeOne() const {
|
| uint32_t validComponentFlags;
|
| GrColor color;
|
| // Check if per-vertex or constant color may have partial alpha
|
| if (this->hasColorVertexAttribute()) {
|
| - validComponentFlags = 0;
|
| - color = 0; // not strictly necessary but we get false alarms from tools about uninit.
|
| + if (fHints & kVertexColorsAreOpaque_Hint) {
|
| + validComponentFlags = kA_GrColorComponentFlag;
|
| + color = 0xFF << GrColor_SHIFT_A;
|
| + } else {
|
| + validComponentFlags = 0;
|
| + color = 0; // not strictly necessary but we get false alarms from tools about uninit.
|
| + }
|
| } else {
|
| validComponentFlags = kRGBA_GrColorComponentFlags;
|
| color = this->getColor();
|
| @@ -455,13 +505,10 @@ GrDrawState::BlendOptFlags GrDrawState::calcBlendOpts(bool forceCoverage,
|
| bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
|
| (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
|
|
|
| - bool covIsZero = !this->isCoverageDrawing() &&
|
| - !this->hasCoverageVertexAttribute() &&
|
| - 0 == this->getCoverageColor();
|
| // When coeffs are (0,1) there is no reason to draw at all, unless
|
| // stenciling is enabled. Having color writes disabled is effectively
|
| - // (0,1). The same applies when coverage is known to be 0.
|
| - if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
|
| + // (0,1).
|
| + if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
|
| if (this->getStencil().doesWrite()) {
|
| return kEmitCoverage_BlendOptFlag;
|
| } else {
|
| @@ -469,11 +516,7 @@ GrDrawState::BlendOptFlags GrDrawState::calcBlendOpts(bool forceCoverage,
|
| }
|
| }
|
|
|
| - // check for coverage due to constant coverage, per-vertex coverage, or coverage stage
|
| - bool hasCoverage = forceCoverage ||
|
| - 0xffffffff != this->getCoverageColor() ||
|
| - this->hasCoverageVertexAttribute() ||
|
| - this->numCoverageStages() > 0;
|
| + bool hasCoverage = forceCoverage || !this->hasSolidCoverage();
|
|
|
| // if we don't have coverage we can check whether the dst
|
| // has to read at all. If not, we'll disable blending.
|
|
|