aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/gpu.gypi2
-rw-r--r--src/gpu/GrDrawState.cpp350
-rw-r--r--src/gpu/GrDrawState.h305
-rw-r--r--src/gpu/GrRODrawState.cpp167
-rw-r--r--src/gpu/GrRODrawState.h381
5 files changed, 682 insertions, 523 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index f00cfac733..4668ac47fd 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -116,6 +116,8 @@
'<(skia_src_path)/gpu/GrResourceCache.h',
'<(skia_src_path)/gpu/GrResourceCache2.cpp',
'<(skia_src_path)/gpu/GrResourceCache2.h',
+ '<(skia_src_path)/gpu/GrRODrawState.cpp',
+ '<(skia_src_path)/gpu/GrRODrawState.h',
'<(skia_src_path)/gpu/GrStencil.cpp',
'<(skia_src_path)/gpu/GrStencil.h',
'<(skia_src_path)/gpu/GrStencilAndCoverPathRenderer.cpp',
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index de97f68291..a6b3d68238 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -14,51 +14,13 @@
GrDrawState::CombinedState GrDrawState::CombineIfPossible(
const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
- bool usingVertexColors = a.hasColorVertexAttribute();
- if (!usingVertexColors && a.fColor != b.fColor) {
+ if (!a.isEqual(b)) {
return kIncompatible_CombinedState;
}
- if (a.fRenderTarget.get() != b.fRenderTarget.get() ||
- a.fColorStages.count() != b.fColorStages.count() ||
- a.fCoverageStages.count() != b.fCoverageStages.count() ||
- !a.fViewMatrix.cheapEqualTo(b.fViewMatrix) ||
- a.fSrcBlend != b.fSrcBlend ||
- a.fDstBlend != b.fDstBlend ||
- a.fBlendConstant != b.fBlendConstant ||
- a.fFlagBits != b.fFlagBits ||
- a.fVACount != b.fVACount ||
- memcmp(a.fVAPtr, b.fVAPtr, a.fVACount * sizeof(GrVertexAttrib)) ||
- a.fStencilSettings != b.fStencilSettings ||
- a.fDrawFace != b.fDrawFace) {
- return kIncompatible_CombinedState;
- }
-
- bool usingVertexCoverage = a.hasCoverageVertexAttribute();
- if (!usingVertexCoverage && a.fCoverage != b.fCoverage) {
- return kIncompatible_CombinedState;
- }
-
- bool explicitLocalCoords = a.hasLocalCoordAttribute();
- for (int i = 0; i < a.numColorStages(); i++) {
- if (!GrEffectStage::AreCompatible(a.getColorStage(i), b.getColorStage(i),
- explicitLocalCoords)) {
- return kIncompatible_CombinedState;
- }
- }
- for (int i = 0; i < a.numCoverageStages(); i++) {
- if (!GrEffectStage::AreCompatible(a.getCoverageStage(i), b.getCoverageStage(i),
- explicitLocalCoords)) {
- return kIncompatible_CombinedState;
- }
- }
-
- SkASSERT(a.fVertexSize == b.fVertexSize);
- SkASSERT(0 == memcmp(a.fFixedFunctionVertexAttribIndices,
- b.fFixedFunctionVertexAttribIndices,
- sizeof(a.fFixedFunctionVertexAttribIndices)));
-
- if (usingVertexColors) {
+ // If the general draw states are equal (from check above) we know hasColorVertexAttribute()
+ // is equivalent for both a and b
+ if (a.hasColorVertexAttribute()) {
// 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.
@@ -221,7 +183,7 @@ static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
#ifdef SK_DEBUG
uint32_t overlapCheck = 0;
#endif
- SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
+ SkASSERT(count <= GrRODrawState::kMaxVertexAttribCnt);
size_t size = 0;
for (int index = 0; index < count; ++index) {
size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
@@ -237,10 +199,6 @@ static size_t vertex_size(const GrVertexAttrib* attribs, int count) {
return size;
}
-size_t GrDrawState::getVertexSize() const {
- return fVertexSize;
-}
-
////////////////////////////////////////////////////////////////////////////////
void GrDrawState::setVertexAttribs(const GrVertexAttrib* attribs, int count) {
@@ -298,65 +256,6 @@ void GrDrawState::setDefaultVertexAttribs() {
////////////////////////////////////////////////////////////////////////////////
-bool GrDrawState::validateVertexAttribs() const {
- // check consistency of effects and attributes
- GrSLType slTypes[kMaxVertexAttribCnt];
- for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
- slTypes[i] = static_cast<GrSLType>(-1);
- }
- int totalStages = this->numTotalStages();
- for (int s = 0; s < totalStages; ++s) {
- int covIdx = s - this->numColorStages();
- const GrEffectStage& stage = covIdx < 0 ? this->getColorStage(s) :
- this->getCoverageStage(covIdx);
- const GrEffect* effect = stage.getEffect();
- SkASSERT(NULL != effect);
- // make sure that any attribute indices have the correct binding type, that the attrib
- // type and effect's shader lang type are compatible, and that attributes shared by
- // multiple effects use the same shader lang type.
- const int* attributeIndices = stage.getVertexAttribIndices();
- int numAttributes = stage.getVertexAttribIndexCount();
- for (int i = 0; i < numAttributes; ++i) {
- int attribIndex = attributeIndices[i];
- if (attribIndex >= fVACount ||
- kEffect_GrVertexAttribBinding != fVAPtr[attribIndex].fBinding) {
- return false;
- }
-
- GrSLType effectSLType = effect->vertexAttribType(i);
- GrVertexAttribType attribType = fVAPtr[attribIndex].fType;
- int slVecCount = GrSLTypeVectorCount(effectSLType);
- int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
- if (slVecCount != attribVecCount ||
- (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
- slTypes[attribIndex] != effectSLType)) {
- return false;
- }
- slTypes[attribIndex] = effectSLType;
- }
- }
-
- return true;
-}
-
-bool GrDrawState::willEffectReadDstColor() const {
- if (!this->isColorWriteDisabled()) {
- for (int s = 0; s < this->numColorStages(); ++s) {
- if (this->getColorStage(s).getEffect()->willReadDstColor()) {
- return true;
- }
- }
- }
- for (int s = 0; s < this->numCoverageStages(); ++s) {
- if (this->getCoverageStage(s).getEffect()->willReadDstColor()) {
- return true;
- }
- }
- return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
if (caps.dualSourceBlendingSupport()) {
return true;
@@ -366,114 +265,52 @@ bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
// 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 ||
+ GrRODrawState::BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
+ return GrRODrawState::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()) {
- 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();
- }
-
- // Run through the color stages
- for (int s = 0; s < this->numColorStages(); ++s) {
- const GrEffect* effect = this->getColorStage(s).getEffect();
- effect->getConstantColorComponents(&color, &validComponentFlags);
- }
-
- // Check whether coverage is treated as color. If so we run through the coverage computation.
- if (this->isCoverageDrawing()) {
- // The shader generated for coverage drawing runs the full coverage computation and then
- // makes the shader output be the multiplication of color and coverage. We mirror that here.
- GrColor coverage;
- uint32_t coverageComponentFlags;
- if (this->hasCoverageVertexAttribute()) {
- coverageComponentFlags = 0;
- coverage = 0; // suppresses any warnings.
- } else {
- coverageComponentFlags = kRGBA_GrColorComponentFlags;
- coverage = this->getCoverageColor();
- }
-
- // Run through the coverage stages
- for (int s = 0; s < this->numCoverageStages(); ++s) {
- const GrEffect* effect = this->getCoverageStage(s).getEffect();
- effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
- }
-
- // Since the shader will multiply coverage and color, the only way the final A==1 is if
- // coverage and color both have A==1.
- return (kA_GrColorComponentFlag & validComponentFlags & coverageComponentFlags) &&
- 0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage);
-
- }
+//////////////////////////////////////////////////////////////////////////////
- return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
+GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(
+ GrDrawState* drawState) {
+ SkASSERT(NULL != drawState);
+ fDrawState = drawState;
+ fVAPtr = drawState->fVAPtr;
+ fVACount = drawState->fVACount;
+ fDrawState->setDefaultVertexAttribs();
}
-bool GrDrawState::hasSolidCoverage() const {
- // If we're drawing coverage directly then coverage is effectively treated as color.
- if (this->isCoverageDrawing()) {
- return true;
- }
+//////////////////////////////////////////////////////////////////////////////s
- GrColor coverage;
- uint32_t validComponentFlags;
- // Initialize to an unknown starting coverage if per-vertex coverage is specified.
- if (this->hasCoverageVertexAttribute()) {
- validComponentFlags = 0;
- } else {
- coverage = this->getCoverageColor();
- validComponentFlags = kRGBA_GrColorComponentFlags;
- }
+void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
+ if (NULL != fDrawState) {
+ int m = fDrawState->numColorStages() - fColorEffectCnt;
+ SkASSERT(m >= 0);
+ fDrawState->fColorStages.pop_back_n(m);
- // Run through the coverage stages and see if the coverage will be all ones at the end.
- for (int s = 0; s < this->numCoverageStages(); ++s) {
- const GrEffect* effect = this->getCoverageStage(s).getEffect();
- effect->getConstantColorComponents(&coverage, &validComponentFlags);
+ int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
+ SkASSERT(n >= 0);
+ fDrawState->fCoverageStages.pop_back_n(n);
+ if (m + n > 0) {
+ fDrawState->invalidateBlendOptFlags();
+ }
+ SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
+ }
+ fDrawState = ds;
+ if (NULL != ds) {
+ fColorEffectCnt = ds->numColorStages();
+ fCoverageEffectCnt = ds->numCoverageStages();
+ SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
}
- return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
}
////////////////////////////////////////////////////////////////////////////////
-// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
-// others will blend incorrectly.
-bool GrDrawState::canTweakAlphaForCoverage() const {
- /*
- The fractional coverage is f.
- The src and dst coeffs are Cs and Cd.
- The dst and src colors are S and D.
- We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
- we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
- term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
- find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
- Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
- color by definition.
- */
- return kOne_GrBlendCoeff == fDstBlend ||
- kISA_GrBlendCoeff == fDstBlend ||
- kISC_GrBlendCoeff == fDstBlend ||
- this->isCoverageDrawing();
-}
-
-GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
- GrBlendCoeff* srcCoeff,
- GrBlendCoeff* dstCoeff) const {
+GrRODrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
+ GrBlendCoeff* srcCoeff,
+ GrBlendCoeff* dstCoeff) const {
GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
if (NULL == srcCoeff) {
srcCoeff = &bogusSrcCoeff;
@@ -499,9 +336,9 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
return fBlendOptFlags;
}
-GrDrawState::BlendOptFlags GrDrawState::calcBlendOpts(bool forceCoverage,
- GrBlendCoeff* srcCoeff,
- GrBlendCoeff* dstCoeff) const {
+GrRODrawState::BlendOptFlags GrDrawState::calcBlendOpts(bool forceCoverage,
+ GrBlendCoeff* srcCoeff,
+ GrBlendCoeff* dstCoeff) const {
*srcCoeff = this->getSrcBlendCoeff();
*dstCoeff = this->getDstBlendCoeff();
@@ -581,49 +418,6 @@ GrDrawState::BlendOptFlags GrDrawState::calcBlendOpts(bool forceCoverage,
return kNone_BlendOpt;
}
-bool GrDrawState::canIgnoreColorAttribute() const {
- if (fBlendOptFlags & kInvalid_BlendOptFlag) {
- this->getBlendOpts();
- }
- return SkToBool(fBlendOptFlags & (GrDrawState::kEmitTransBlack_BlendOptFlag |
- GrDrawState::kEmitCoverage_BlendOptFlag));
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(
- GrDrawState* drawState) {
- SkASSERT(NULL != drawState);
- fDrawState = drawState;
- fVAPtr = drawState->fVAPtr;
- fVACount = drawState->fVACount;
- fDrawState->setDefaultVertexAttribs();
-}
-
-//////////////////////////////////////////////////////////////////////////////s
-
-void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
- if (NULL != fDrawState) {
- int m = fDrawState->numColorStages() - fColorEffectCnt;
- SkASSERT(m >= 0);
- fDrawState->fColorStages.pop_back_n(m);
-
- int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
- SkASSERT(n >= 0);
- fDrawState->fCoverageStages.pop_back_n(n);
- if (m + n > 0) {
- fDrawState->invalidateBlendOptFlags();
- }
- SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
- }
- fDrawState = ds;
- if (NULL != ds) {
- fColorEffectCnt = ds->numColorStages();
- fCoverageEffectCnt = ds->numCoverageStages();
- SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
- }
-}
-
////////////////////////////////////////////////////////////////////////////////
void GrDrawState::AutoViewMatrixRestore::restore() {
@@ -710,3 +504,67 @@ void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& co
fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
}
}
+
+bool GrDrawState::srcAlphaWillBeOne() const {
+ uint32_t validComponentFlags;
+ GrColor color;
+ // Check if per-vertex or constant color may have partial alpha
+ if (this->hasColorVertexAttribute()) {
+ 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();
+ }
+
+ // Run through the color stages
+ for (int s = 0; s < this->numColorStages(); ++s) {
+ const GrEffect* effect = this->getColorStage(s).getEffect();
+ effect->getConstantColorComponents(&color, &validComponentFlags);
+ }
+
+ // Check whether coverage is treated as color. If so we run through the coverage computation.
+ if (this->isCoverageDrawing()) {
+ // The shader generated for coverage drawing runs the full coverage computation and then
+ // makes the shader output be the multiplication of color and coverage. We mirror that here.
+ GrColor coverage;
+ uint32_t coverageComponentFlags;
+ if (this->hasCoverageVertexAttribute()) {
+ coverageComponentFlags = 0;
+ coverage = 0; // suppresses any warnings.
+ } else {
+ coverageComponentFlags = kRGBA_GrColorComponentFlags;
+ coverage = this->getCoverageColor();
+ }
+
+ // Run through the coverage stages
+ for (int s = 0; s < this->numCoverageStages(); ++s) {
+ const GrEffect* effect = this->getCoverageStage(s).getEffect();
+ effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
+ }
+
+ // Since the shader will multiply coverage and color, the only way the final A==1 is if
+ // coverage and color both have A==1.
+ return (kA_GrColorComponentFlag & validComponentFlags & coverageComponentFlags) &&
+ 0xFF == GrColorUnpackA(color) && 0xFF == GrColorUnpackA(coverage);
+
+ }
+
+ return (kA_GrColorComponentFlag & validComponentFlags) && 0xFF == GrColorUnpackA(color);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool GrDrawState::canIgnoreColorAttribute() const {
+ if (fBlendOptFlags & kInvalid_BlendOptFlag) {
+ this->getBlendOpts();
+ }
+ return SkToBool(fBlendOptFlags & (GrRODrawState::kEmitTransBlack_BlendOptFlag |
+ GrRODrawState::kEmitCoverage_BlendOptFlag));
+}
+
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index cc1df05ec3..dcd6ff9aaf 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -8,20 +8,18 @@
#ifndef GrDrawState_DEFINED
#define GrDrawState_DEFINED
+#include "GrRODrawState.h"
+
#include "GrBlend.h"
-#include "GrColor.h"
-#include "GrEffectStage.h"
-#include "GrStencil.h"
#include "effects/GrSimpleTextureEffect.h"
-#include "SkMatrix.h"
-
-class GrDrawTargetCaps;
-class GrPaint;
-class GrRenderTarget;
-class GrTexture;
-
-class GrDrawState : public SkRefCnt {
+/**
+ * Modifiable subclass derived from GrRODrawState. The majority of the data that represents a draw
+ * state is stored in the parent class. GrDrawState contains methods for setting, adding to, etc.
+ * various data members of the draw state. This class is used to configure the state used when
+ * issuing draws via GrDrawTarget.
+ */
+class GrDrawState : public GrRODrawState {
public:
SK_DECLARE_INST_COUNT(GrDrawState)
@@ -69,10 +67,6 @@ public:
/// @name Vertex Attributes
////
- enum {
- kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
- };
-
/**
* The format of vertices is represented as an array of GrVertexAttribs, with each representing
* the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
@@ -90,11 +84,6 @@ public:
this->setVertexAttribs(A, count);
}
- const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
- int getVertexAttribCount() const { return fVACount; }
-
- size_t getVertexSize() const;
-
/**
* Sets default vertex attributes for next draw. The default is a single attribute:
* {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
@@ -102,37 +91,6 @@ public:
void setDefaultVertexAttribs();
/**
- * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
- * binding does not appear in the current attribs. These bindings should appear only once in
- * the attrib array.
- */
-
- int positionAttributeIndex() const {
- return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
- }
- int localCoordAttributeIndex() const {
- return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
- }
- int colorVertexAttributeIndex() const {
- return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
- }
- int coverageVertexAttributeIndex() const {
- return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
- }
-
- bool hasLocalCoordAttribute() const {
- return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
- }
- bool hasColorVertexAttribute() const {
- return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
- }
- bool hasCoverageVertexAttribute() const {
- return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
- }
-
- bool validateVertexAttribs() const;
-
- /**
* Helper to save/restore vertex attribs
*/
class AutoVertexAttribRestore {
@@ -150,16 +108,6 @@ public:
/// @}
/**
- * Determines whether src alpha is guaranteed to be one for all src pixels
- */
- bool srcAlphaWillBeOne() const;
-
- /**
- * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
- */
- bool hasSolidCoverage() const;
-
- /**
* Depending on features available in the underlying 3D API and the color blend mode requested
* it may or may not be possible to correctly blend with fractional pixel coverage generated by
* the fragment shader.
@@ -187,8 +135,6 @@ public:
this->invalidateBlendOptFlags();
}
- GrColor getColor() const { return fColor; }
-
/**
* Sets the color to be used for the next draw to be
* (r,g,b,a) = (alpha, alpha, alpha, alpha).
@@ -213,12 +159,6 @@ public:
this->invalidateBlendOptFlags();
}
- uint8_t getCoverage() const { return fCoverage; }
-
- GrColor getCoverageColor() const {
- return GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
- }
-
/// @}
///////////////////////////////////////////////////////////////////////////
@@ -302,18 +242,6 @@ public:
int fCoverageEffectCnt;
};
- int numColorStages() const { return fColorStages.count(); }
- int numCoverageStages() const { return fCoverageStages.count(); }
- int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
-
- const GrEffectStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
- const GrEffectStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; }
-
- /**
- * Checks whether any of the effects will read the dst pixel color.
- */
- bool willEffectReadDstColor() const;
-
/// @}
///////////////////////////////////////////////////////////////////////////
@@ -347,15 +275,6 @@ public:
#endif
}
- GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
- GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
-
- void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
- GrBlendCoeff* dstBlendCoeff) const {
- *srcBlendCoeff = fSrcBlend;
- *dstBlendCoeff = fDstBlend;
- }
-
/**
* Sets the blending function constant referenced by the following blending
* coefficients:
@@ -372,63 +291,6 @@ public:
}
/**
- * Retrieves the last value set by setBlendConstant()
- * @return the blending constant value
- */
- GrColor getBlendConstant() const { return fBlendConstant; }
-
- /**
- * Determines whether multiplying the computed per-pixel color by the pixel's fractional
- * coverage before the blend will give the correct final destination color. In general it
- * will not as coverage is applied after blending.
- */
- bool canTweakAlphaForCoverage() const;
-
- /**
- * Optimizations for blending / coverage to that can be applied based on the current state.
- */
- enum BlendOptFlags {
- /**
- * No optimization
- */
- kNone_BlendOpt = 0,
- /**
- * Don't draw at all
- */
- kSkipDraw_BlendOptFlag = 0x1,
- /**
- * The coverage value does not have to be computed separately from alpha, the the output
- * color can be the modulation of the two.
- */
- kCoverageAsAlpha_BlendOptFlag = 0x2,
- /**
- * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
- * "don't cares".
- */
- kEmitCoverage_BlendOptFlag = 0x4,
- /**
- * Emit transparent black instead of the src color, no need to compute coverage.
- */
- kEmitTransBlack_BlendOptFlag = 0x8,
- /**
- * Flag used to invalidate the cached BlendOptFlags, OptSrcCoeff, and OptDstCoeff cached by
- * the get BlendOpts function.
- */
- kInvalid_BlendOptFlag = 1 << 31,
- };
- GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
-
- void invalidateBlendOptFlags() {
- fBlendOptFlags = kInvalid_BlendOptFlag;
- }
-
- /**
- * We don't use suplied vertex color attributes if our blend mode is EmitCoverage or
- * EmitTransBlack
- */
- bool canIgnoreColorAttribute() const;
-
- /**
* Determines what optimizations can be applied based on the blend. The coefficients may have
* to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
* params that receive the tweaked coefficients. Normally the function looks at the current
@@ -445,6 +307,13 @@ public:
GrBlendCoeff* srcCoeff = NULL,
GrBlendCoeff* dstCoeff = NULL) const;
+ /**
+ * We don't use suplied vertex color attributes if our blend mode is EmitCoverage or
+ * EmitTransBlack
+ */
+ bool canIgnoreColorAttribute() const;
+
+
/// @}
///////////////////////////////////////////////////////////////////////////
@@ -457,34 +326,6 @@ public:
*/
bool setIdentityViewMatrix();
- /**
- * Retrieves the current view matrix
- * @return the current view matrix.
- */
- const SkMatrix& getViewMatrix() const { return fViewMatrix; }
-
- /**
- * Retrieves the inverse of the current view matrix.
- *
- * If the current view matrix is invertible, return true, and if matrix
- * is non-null, copy the inverse into it. If the current view matrix is
- * non-invertible, return false and ignore the matrix parameter.
- *
- * @param matrix if not null, will receive a copy of the current inverse.
- */
- bool getViewInverse(SkMatrix* matrix) const {
- // TODO: determine whether we really need to leave matrix unmodified
- // at call sites when inversion fails.
- SkMatrix inverse;
- if (fViewMatrix.invert(&inverse)) {
- if (matrix) {
- *matrix = inverse;
- }
- return true;
- }
- return false;
- }
-
////////////////////////////////////////////////////////////////////////////
/**
@@ -535,14 +376,6 @@ public:
*/
void setRenderTarget(GrRenderTarget* target) { fRenderTarget.reset(SkSafeRef(target)); }
- /**
- * Retrieves the currently set render-target.
- *
- * @return The currently set render target.
- */
- const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
- GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
-
class AutoRenderTargetRestore : public ::SkNoncopyable {
public:
AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
@@ -603,8 +436,6 @@ public:
this->invalidateBlendOptFlags();
}
- const GrStencilSettings& getStencil() const { return fStencilSettings; }
-
GrStencilSettings* stencil() { return &fStencilSettings; }
/// @}
@@ -613,46 +444,6 @@ public:
/// @name State Flags
////
- /**
- * Flags that affect rendering. Controlled using enable/disableState(). All
- * default to disabled.
- */
- enum StateBits {
- /**
- * Perform dithering. TODO: Re-evaluate whether we need this bit
- */
- kDither_StateBit = 0x01,
- /**
- * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
- * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
- * the 3D API.
- */
- kHWAntialias_StateBit = 0x02,
- /**
- * Draws will respect the clip, otherwise the clip is ignored.
- */
- kClip_StateBit = 0x04,
- /**
- * Disables writing to the color buffer. Useful when performing stencil
- * operations.
- */
- kNoColorWrites_StateBit = 0x08,
-
- /**
- * Usually coverage is applied after color blending. The color is blended using the coeffs
- * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
- * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
- * this case there is no distinction between coverage and color and the caller needs direct
- * control over the blend coeffs. When set, there will be a single blend step controlled by
- * setBlendFunc() which will use coverage*color as the src color.
- */
- kCoverageDrawing_StateBit = 0x10,
-
- // Users of the class may add additional bits to the vector
- kDummyStateBit,
- kLastPublicStateBit = kDummyStateBit-1,
- };
-
void resetStateFlags() {
fFlagBits = 0;
this->invalidateBlendOptFlags();
@@ -692,28 +483,12 @@ public:
}
}
- bool isStateFlagEnabled(uint32_t stateBit) const { return 0 != (stateBit & fFlagBits); }
-
- bool isDitherState() const { return 0 != (fFlagBits & kDither_StateBit); }
- bool isHWAntialiasState() const { return 0 != (fFlagBits & kHWAntialias_StateBit); }
- bool isClipState() const { return 0 != (fFlagBits & kClip_StateBit); }
- bool isColorWriteDisabled() const { return 0 != (fFlagBits & kNoColorWrites_StateBit); }
- bool isCoverageDrawing() const { return 0 != (fFlagBits & kCoverageDrawing_StateBit); }
-
/// @}
///////////////////////////////////////////////////////////////////////////
/// @name Face Culling
////
- enum DrawFace {
- kInvalid_DrawFace = -1,
-
- kBoth_DrawFace,
- kCCW_DrawFace,
- kCW_DrawFace,
- };
-
/**
* Controls whether clockwise, counterclockwise, or both faces are drawn.
* @param face the face(s) to draw.
@@ -723,13 +498,6 @@ public:
fDrawFace = face;
}
- /**
- * Gets whether the target is drawing clockwise, counterclockwise,
- * or both faces.
- * @return the current draw face(s).
- */
- DrawFace getDrawFace() const { return fDrawFace; }
-
/// @}
///////////////////////////////////////////////////////////////////////////
@@ -769,38 +537,23 @@ public:
private:
void onReset(const SkMatrix* initialViewMatrix);
+ /**
+ * Determines whether src alpha is guaranteed to be one for all src pixels
+ */
+ bool srcAlphaWillBeOne() const;
+
+ /**
+ * Helper function for getBlendOpts.
+ */
BlendOptFlags calcBlendOpts(bool forceCoverage = false,
GrBlendCoeff* srcCoeff = NULL,
GrBlendCoeff* dstCoeff = NULL) const;
- // These fields are roughly sorted by decreasing likelihood of being different in op==
- SkAutoTUnref<GrRenderTarget> fRenderTarget;
- GrColor fColor;
- SkMatrix fViewMatrix;
- GrBlendCoeff fSrcBlend;
- GrBlendCoeff fDstBlend;
- GrColor fBlendConstant;
- uint32_t fFlagBits;
- const GrVertexAttrib* fVAPtr;
- int fVACount;
- size_t fVertexSize;
- GrStencilSettings fStencilSettings;
- uint8_t fCoverage;
- DrawFace fDrawFace;
-
- typedef SkSTArray<4, GrEffectStage> EffectStageArray;
- EffectStageArray fColorStages;
- EffectStageArray fCoverageStages;
+ void invalidateBlendOptFlags() {
+ fBlendOptFlags = kInvalid_BlendOptFlag;
+ }
uint32_t fHints;
-
- mutable GrBlendCoeff fOptSrcBlend;
- mutable GrBlendCoeff fOptDstBlend;
- mutable BlendOptFlags fBlendOptFlags;
-
- // This is simply a different representation of info in fVertexAttribs and thus does
- // not need to be compared in op==.
- int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
// Some of the auto restore objects assume that no effects are removed during their lifetime.
// This is used to assert that this condition holds.
@@ -814,9 +567,7 @@ private:
*/
void setVertexAttribs(const GrVertexAttrib attribs[], int count);
- typedef SkRefCnt INHERITED;
+ typedef GrRODrawState INHERITED;
};
-GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
-
#endif
diff --git a/src/gpu/GrRODrawState.cpp b/src/gpu/GrRODrawState.cpp
new file mode 100644
index 0000000000..1460f57320
--- /dev/null
+++ b/src/gpu/GrRODrawState.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrRODrawState.h"
+#include "GrDrawTargetCaps.h"
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool GrRODrawState::isEqual(const GrRODrawState& that) const {
+ bool usingVertexColors = this->hasColorVertexAttribute();
+ if (!usingVertexColors && this->fColor != that.fColor) {
+ return false;
+ }
+
+ if (this->fRenderTarget.get() != that.fRenderTarget.get() ||
+ this->fColorStages.count() != that.fColorStages.count() ||
+ this->fCoverageStages.count() != that.fCoverageStages.count() ||
+ !this->fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
+ this->fSrcBlend != that.fSrcBlend ||
+ this->fDstBlend != that.fDstBlend ||
+ this->fBlendConstant != that.fBlendConstant ||
+ this->fFlagBits != that.fFlagBits ||
+ this->fVACount != that.fVACount ||
+ memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
+ this->fStencilSettings != that.fStencilSettings ||
+ this->fDrawFace != that.fDrawFace) {
+ return false;
+ }
+
+ bool usingVertexCoverage = this->hasCoverageVertexAttribute();
+ if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
+ return false;
+ }
+
+ bool explicitLocalCoords = this->hasLocalCoordAttribute();
+ for (int i = 0; i < this->numColorStages(); i++) {
+ if (!GrEffectStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
+ explicitLocalCoords)) {
+ return false;
+ }
+ }
+ for (int i = 0; i < this->numCoverageStages(); i++) {
+ if (!GrEffectStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
+ explicitLocalCoords)) {
+ return false;
+ }
+ }
+
+ SkASSERT(this->fVertexSize == that.fVertexSize);
+ SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
+ that.fFixedFunctionVertexAttribIndices,
+ sizeof(this->fFixedFunctionVertexAttribIndices)));
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool GrRODrawState::validateVertexAttribs() const {
+ // check consistency of effects and attributes
+ GrSLType slTypes[kMaxVertexAttribCnt];
+ for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
+ slTypes[i] = static_cast<GrSLType>(-1);
+ }
+ int totalStages = this->numTotalStages();
+ for (int s = 0; s < totalStages; ++s) {
+ int covIdx = s - this->numColorStages();
+ const GrEffectStage& stage = covIdx < 0 ? this->getColorStage(s) :
+ this->getCoverageStage(covIdx);
+ const GrEffect* effect = stage.getEffect();
+ SkASSERT(NULL != effect);
+ // make sure that any attribute indices have the correct binding type, that the attrib
+ // type and effect's shader lang type are compatible, and that attributes shared by
+ // multiple effects use the same shader lang type.
+ const int* attributeIndices = stage.getVertexAttribIndices();
+ int numAttributes = stage.getVertexAttribIndexCount();
+ for (int i = 0; i < numAttributes; ++i) {
+ int attribIndex = attributeIndices[i];
+ if (attribIndex >= fVACount ||
+ kEffect_GrVertexAttribBinding != fVAPtr[attribIndex].fBinding) {
+ return false;
+ }
+
+ GrSLType effectSLType = effect->vertexAttribType(i);
+ GrVertexAttribType attribType = fVAPtr[attribIndex].fType;
+ int slVecCount = GrSLTypeVectorCount(effectSLType);
+ int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
+ if (slVecCount != attribVecCount ||
+ (static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
+ slTypes[attribIndex] != effectSLType)) {
+ return false;
+ }
+ slTypes[attribIndex] = effectSLType;
+ }
+ }
+
+ return true;
+}
+
+bool GrRODrawState::hasSolidCoverage() const {
+ // If we're drawing coverage directly then coverage is effectively treated as color.
+ if (this->isCoverageDrawing()) {
+ return true;
+ }
+
+ GrColor coverage;
+ uint32_t validComponentFlags;
+ // Initialize to an unknown starting coverage if per-vertex coverage is specified.
+ if (this->hasCoverageVertexAttribute()) {
+ validComponentFlags = 0;
+ } else {
+ coverage = fCoverage;
+ validComponentFlags = kRGBA_GrColorComponentFlags;
+ }
+
+ // Run through the coverage stages and see if the coverage will be all ones at the end.
+ for (int s = 0; s < this->numCoverageStages(); ++s) {
+ const GrEffect* effect = this->getCoverageStage(s).getEffect();
+ effect->getConstantColorComponents(&coverage, &validComponentFlags);
+ }
+ return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool GrRODrawState::willEffectReadDstColor() const {
+ if (!this->isColorWriteDisabled()) {
+ for (int s = 0; s < this->numColorStages(); ++s) {
+ if (this->getColorStage(s).getEffect()->willReadDstColor()) {
+ return true;
+ }
+ }
+ }
+ for (int s = 0; s < this->numCoverageStages(); ++s) {
+ if (this->getCoverageStage(s).getEffect()->willReadDstColor()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Some blend modes allow folding a fractional coverage value into the color's alpha channel, while
+// others will blend incorrectly.
+bool GrRODrawState::canTweakAlphaForCoverage() const {
+ /*
+ The fractional coverage is f.
+ The src and dst coeffs are Cs and Cd.
+ The dst and src colors are S and D.
+ We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D. By tweaking the source color's alpha
+ we're replacing S with S'=fS. It's obvious that that first term will always be ok. The second
+ term can be rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities for Cd we
+ find that only 1, ISA, and ISC produce the correct destination when applied to S' and D.
+ Also, if we're directly rendering coverage (isCoverageDrawing) then coverage is treated as
+ color by definition.
+ */
+ return kOne_GrBlendCoeff == fDstBlend ||
+ kISA_GrBlendCoeff == fDstBlend ||
+ kISC_GrBlendCoeff == fDstBlend ||
+ this->isCoverageDrawing();
+}
+
diff --git a/src/gpu/GrRODrawState.h b/src/gpu/GrRODrawState.h
new file mode 100644
index 0000000000..231560854f
--- /dev/null
+++ b/src/gpu/GrRODrawState.h
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrRODrawState_DEFINED
+#define GrRODrawState_DEFINED
+
+#include "GrStencil.h"
+#include "GrEffectStage.h"
+#include "SkMatrix.h"
+
+class GrDrawTargetCaps;
+class GrPaint;
+class GrRenderTarget;
+class GrTexture;
+
+/**
+ * Read-only base class for GrDrawState. This class contains all the necessary data to represent a
+ * canonical DrawState. All methods in the class are const, thus once created the data in the class
+ * cannot be changed.
+ */
+class GrRODrawState : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrRODrawState)
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Vertex Attributes
+ ////
+
+ enum {
+ kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
+ };
+
+ const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
+ int getVertexAttribCount() const { return fVACount; }
+
+ size_t getVertexSize() const { return fVertexSize; }
+
+ /**
+ * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
+ * binding does not appear in the current attribs. These bindings should appear only once in
+ * the attrib array.
+ */
+
+ int positionAttributeIndex() const {
+ return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
+ }
+ int localCoordAttributeIndex() const {
+ return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
+ }
+ int colorVertexAttributeIndex() const {
+ return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
+ }
+ int coverageVertexAttributeIndex() const {
+ return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
+ }
+
+ bool hasLocalCoordAttribute() const {
+ return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
+ }
+ bool hasColorVertexAttribute() const {
+ return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
+ }
+ bool hasCoverageVertexAttribute() const {
+ return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
+ }
+
+ bool validateVertexAttribs() const;
+
+ /// @}
+
+ /**
+ * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
+ */
+ bool hasSolidCoverage() const;
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Color
+ ////
+
+ GrColor getColor() const { return fColor; }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Coverage
+ ////
+
+ uint8_t getCoverage() const { return fCoverage; }
+
+ GrColor getCoverageColor() const {
+ return GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
+ }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Effect Stages
+ /// Each stage hosts a GrEffect. The effect produces an output color or coverage in the fragment
+ /// shader. Its inputs are the output from the previous stage as well as some variables
+ /// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color,
+ /// the fragment position, local coordinates).
+ ///
+ /// The stages are divided into two sets, color-computing and coverage-computing. The final
+ /// color stage produces the final pixel color. The coverage-computing stages function exactly
+ /// as the color-computing but the output of the final coverage stage is treated as a fractional
+ /// pixel coverage rather than as input to the src/dst color blend step.
+ ///
+ /// The input color to the first color-stage is either the constant color or interpolated
+ /// per-vertex colors. The input to the first coverage stage is either a constant coverage
+ /// (usually full-coverage) or interpolated per-vertex coverage.
+ ///
+ /// See the documentation of kCoverageDrawing_StateBit for information about disabling the
+ /// the color / coverage distinction.
+ ////
+
+ int numColorStages() const { return fColorStages.count(); }
+ int numCoverageStages() const { return fCoverageStages.count(); }
+ int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
+
+ const GrEffectStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
+ const GrEffectStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; }
+
+ /**
+ * Checks whether any of the effects will read the dst pixel color.
+ */
+ bool willEffectReadDstColor() const;
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Blending
+ ////
+
+ GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
+ GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
+
+ void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
+ GrBlendCoeff* dstBlendCoeff) const {
+ *srcBlendCoeff = fSrcBlend;
+ *dstBlendCoeff = fDstBlend;
+ }
+
+ /**
+ * Retrieves the last value set by setBlendConstant()
+ * @return the blending constant value
+ */
+ GrColor getBlendConstant() const { return fBlendConstant; }
+
+ /**
+ * Determines whether multiplying the computed per-pixel color by the pixel's fractional
+ * coverage before the blend will give the correct final destination color. In general it
+ * will not as coverage is applied after blending.
+ */
+ bool canTweakAlphaForCoverage() const;
+
+ /**
+ * Optimizations for blending / coverage to that can be applied based on the current state.
+ */
+ enum BlendOptFlags {
+ /**
+ * No optimization
+ */
+ kNone_BlendOpt = 0,
+ /**
+ * Don't draw at all
+ */
+ kSkipDraw_BlendOptFlag = 0x1,
+ /**
+ * The coverage value does not have to be computed separately from alpha, the output
+ * color can be the modulation of the two.
+ */
+ kCoverageAsAlpha_BlendOptFlag = 0x2,
+ /**
+ * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
+ * "don't cares".
+ */
+ kEmitCoverage_BlendOptFlag = 0x4,
+ /**
+ * Emit transparent black instead of the src color, no need to compute coverage.
+ */
+ kEmitTransBlack_BlendOptFlag = 0x8,
+ /**
+ * Flag used to invalidate the cached BlendOptFlags, OptSrcCoeff, and OptDstCoeff cached by
+ * the get BlendOpts function.
+ */
+ kInvalid_BlendOptFlag = 1 << 31,
+ };
+ GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name View Matrix
+ ////
+
+ /**
+ * Retrieves the current view matrix
+ * @return the current view matrix.
+ */
+ const SkMatrix& getViewMatrix() const { return fViewMatrix; }
+
+ /**
+ * Retrieves the inverse of the current view matrix.
+ *
+ * If the current view matrix is invertible, return true, and if matrix
+ * is non-null, copy the inverse into it. If the current view matrix is
+ * non-invertible, return false and ignore the matrix parameter.
+ *
+ * @param matrix if not null, will receive a copy of the current inverse.
+ */
+ bool getViewInverse(SkMatrix* matrix) const {
+ // TODO: determine whether we really need to leave matrix unmodified
+ // at call sites when inversion fails.
+ SkMatrix inverse;
+ if (fViewMatrix.invert(&inverse)) {
+ if (matrix) {
+ *matrix = inverse;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Render Target
+ ////
+
+ /**
+ * Retrieves the currently set render-target.
+ *
+ * @return The currently set render target.
+ */
+ const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
+ GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Stencil
+ ////
+
+ const GrStencilSettings& getStencil() const { return fStencilSettings; }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name State Flags
+ ////
+
+ /**
+ * Flags that affect rendering. Controlled using enable/disableState(). All
+ * default to disabled.
+ */
+ enum StateBits {
+ /**
+ * Perform dithering. TODO: Re-evaluate whether we need this bit
+ */
+ kDither_StateBit = 0x01,
+ /**
+ * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
+ * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
+ * the 3D API.
+ */
+ kHWAntialias_StateBit = 0x02,
+ /**
+ * Draws will respect the clip, otherwise the clip is ignored.
+ */
+ kClip_StateBit = 0x04,
+ /**
+ * Disables writing to the color buffer. Useful when performing stencil
+ * operations.
+ */
+ kNoColorWrites_StateBit = 0x08,
+
+ /**
+ * Usually coverage is applied after color blending. The color is blended using the coeffs
+ * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
+ * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
+ * this case there is no distinction between coverage and color and the caller needs direct
+ * control over the blend coeffs. When set, there will be a single blend step controlled by
+ * setBlendFunc() which will use coverage*color as the src color.
+ */
+ kCoverageDrawing_StateBit = 0x10,
+
+ // Users of the class may add additional bits to the vector
+ kDummyStateBit,
+ kLastPublicStateBit = kDummyStateBit-1,
+ };
+
+ bool isStateFlagEnabled(uint32_t stateBit) const { return 0 != (stateBit & fFlagBits); }
+
+ bool isDitherState() const { return 0 != (fFlagBits & kDither_StateBit); }
+ bool isHWAntialiasState() const { return 0 != (fFlagBits & kHWAntialias_StateBit); }
+ bool isClipState() const { return 0 != (fFlagBits & kClip_StateBit); }
+ bool isColorWriteDisabled() const { return 0 != (fFlagBits & kNoColorWrites_StateBit); }
+ bool isCoverageDrawing() const { return 0 != (fFlagBits & kCoverageDrawing_StateBit); }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Face Culling
+ ////
+
+ enum DrawFace {
+ kInvalid_DrawFace = -1,
+
+ kBoth_DrawFace,
+ kCCW_DrawFace,
+ kCW_DrawFace,
+ };
+
+ /**
+ * Gets whether the target is drawing clockwise, counterclockwise,
+ * or both faces.
+ * @return the current draw face(s).
+ */
+ DrawFace getDrawFace() const { return fDrawFace; }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ /** Return type for CombineIfPossible. */
+ enum CombinedState {
+ /** The GrDrawStates cannot be combined. */
+ kIncompatible_CombinedState,
+ /** Either draw state can be used in place of the other. */
+ kAOrB_CombinedState,
+ /** Use the first draw state. */
+ kA_CombinedState,
+ /** Use the second draw state. */
+ kB_CombinedState,
+ };
+
+ GrRODrawState& operator= (const GrRODrawState& that);
+
+protected:
+ bool isEqual(const GrRODrawState& that) const;
+
+ // These fields are roughly sorted by decreasing likelihood of being different in op==
+ SkAutoTUnref<GrRenderTarget> fRenderTarget;
+ GrColor fColor;
+ SkMatrix fViewMatrix;
+ GrColor fBlendConstant;
+ uint32_t fFlagBits;
+ const GrVertexAttrib* fVAPtr;
+ int fVACount;
+ size_t fVertexSize;
+ GrStencilSettings fStencilSettings;
+ uint8_t fCoverage;
+ DrawFace fDrawFace;
+ GrBlendCoeff fSrcBlend;
+ GrBlendCoeff fDstBlend;
+
+ typedef SkSTArray<4, GrEffectStage> EffectStageArray;
+ EffectStageArray fColorStages;
+ EffectStageArray fCoverageStages;
+
+ mutable GrBlendCoeff fOptSrcBlend;
+ mutable GrBlendCoeff fOptDstBlend;
+ mutable BlendOptFlags fBlendOptFlags;
+
+ // This is simply a different representation of info in fVertexAttribs and thus does
+ // not need to be compared in op==.
+ int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
+
+private:
+ typedef SkRefCnt INHERITED;
+};
+
+GR_MAKE_BITFIELD_OPS(GrRODrawState::BlendOptFlags);
+
+#endif