aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/gpu.gypi2
-rw-r--r--include/gpu/GrGpuResourceRef.h3
-rw-r--r--src/gpu/GrDrawState.cpp342
-rw-r--r--src/gpu/GrDrawState.h288
-rw-r--r--src/gpu/GrDrawTarget.h4
-rw-r--r--src/gpu/GrOptDrawState.cpp79
-rw-r--r--src/gpu/GrOptDrawState.h326
-rw-r--r--src/gpu/GrRODrawState.cpp350
-rw-r--r--src/gpu/GrRODrawState.h438
-rw-r--r--src/gpu/gl/GrGpuGL.cpp2
-rw-r--r--src/gpu/gl/GrGpuGL.h2
11 files changed, 1018 insertions, 818 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index ebc07b264b..ec7ced4dab 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -132,8 +132,6 @@
'<(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/include/gpu/GrGpuResourceRef.h b/include/gpu/GrGpuResourceRef.h
index 6b3937b5c7..3320dc069f 100644
--- a/include/gpu/GrGpuResourceRef.h
+++ b/include/gpu/GrGpuResourceRef.h
@@ -75,7 +75,8 @@ private:
called. */
void pendingIOComplete() const;
- friend class GrRODrawState;
+ friend class GrDrawState;
+ friend class GrOptDrawState;
friend class GrProgramElement;
GrGpuResource* fResource;
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index 168cf0b9c3..872d20a1ab 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -16,14 +16,16 @@ GrOptDrawState* GrDrawState::createOptState(const GrDrawTargetCaps& caps) const
if (NULL == fCachedOptState || caps.getUniqueID() != fCachedCapsID) {
GrBlendCoeff srcCoeff;
GrBlendCoeff dstCoeff;
- BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
+ GrOptDrawState::BlendOptFlags blendFlags =
+ (GrOptDrawState::BlendOptFlags) this->getBlendOpts(false, &srcCoeff, &dstCoeff);
fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this, blendFlags, srcCoeff, dstCoeff, caps));
fCachedCapsID = caps.getUniqueID();
} else {
#ifdef SK_DEBUG
GrBlendCoeff srcCoeff;
GrBlendCoeff dstCoeff;
- BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
+ GrOptDrawState::BlendOptFlags blendFlags =
+ (GrOptDrawState::BlendOptFlags) this->getBlendOpts(false, &srcCoeff, &dstCoeff);
SkASSERT(GrOptDrawState(*this, blendFlags, srcCoeff, dstCoeff, caps) == *fCachedOptState);
#endif
}
@@ -33,6 +35,66 @@ GrOptDrawState* GrDrawState::createOptState(const GrDrawTargetCaps& caps) const
//////////////////////////////////////////////////////////////////////////////s
+bool GrDrawState::isEqual(const GrDrawState& that) const {
+ bool usingVertexColors = this->hasColorVertexAttribute();
+ if (!usingVertexColors && this->fColor != that.fColor) {
+ return false;
+ }
+
+ if (this->getRenderTarget() != that.getRenderTarget() ||
+ 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 ||
+ this->fVAStride != that.fVAStride ||
+ 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();
+ if (this->hasGeometryProcessor()) {
+ if (!that.hasGeometryProcessor()) {
+ return false;
+ } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
+ *that.getGeometryProcessor(),
+ explicitLocalCoords)) {
+ return false;
+ }
+ } else if (that.hasGeometryProcessor()) {
+ return false;
+ }
+
+ for (int i = 0; i < this->numColorStages(); i++) {
+ if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
+ explicitLocalCoords)) {
+ return false;
+ }
+ }
+ for (int i = 0; i < this->numCoverageStages(); i++) {
+ if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
+ explicitLocalCoords)) {
+ return false;
+ }
+ }
+
+ SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
+ that.fFixedFunctionVertexAttribIndices,
+ sizeof(this->fFixedFunctionVertexAttribIndices)));
+
+ return true;
+}
+
GrDrawState::CombinedState GrDrawState::CombineIfPossible(
const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
@@ -218,11 +280,54 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende
////////////////////////////////////////////////////////////////////////////////
+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);
+ }
+
+ if (this->hasGeometryProcessor()) {
+ const GrGeometryStage& stage = *this->getGeometryProcessor();
+ const GrGeometryProcessor* gp = stage.getGeometryProcessor();
+ SkASSERT(gp);
+ // 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 GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
+
+ int effectIndex = 0;
+ for (int index = 0; index < fVACount; index++) {
+ if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
+ // we only care about effect bindings
+ continue;
+ }
+ SkASSERT(effectIndex < s.count());
+ GrSLType effectSLType = s[effectIndex].getType();
+ GrVertexAttribType attribType = fVAPtr[index].fType;
+ int slVecCount = GrSLTypeVectorCount(effectSLType);
+ int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
+ if (slVecCount != attribVecCount ||
+ (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
+ return false;
+ }
+ slTypes[index] = effectSLType;
+ effectIndex++;
+ }
+ // Make sure all attributes are consumed and we were able to find everything
+ SkASSERT(s.count() == effectIndex);
+ }
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
// this works as long as we're 4 byte-aligned
#ifdef SK_DEBUG
uint32_t overlapCheck = 0;
- SkASSERT(count <= GrRODrawState::kMaxVertexAttribCnt);
+ SkASSERT(count <= GrDrawState::kMaxVertexAttribCnt);
for (int index = 0; index < count; ++index) {
size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
size_t attribOffset = attribs[index].fOffset;
@@ -305,11 +410,39 @@ bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
GrBlendCoeff srcCoeff;
GrBlendCoeff dstCoeff;
BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
- return GrRODrawState::kNone_BlendOpt != flag ||
+ return GrDrawState::kNone_BlendOpt != flag ||
(this->willEffectReadDstColor() &&
kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
}
+bool GrDrawState::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.
+ if (this->hasGeometryProcessor()) {
+ const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
+ gp->getConstantColorComponents(&coverage, &validComponentFlags);
+ }
+ for (int s = 0; s < this->numCoverageStages(); ++s) {
+ const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
+ processor->getConstantColorComponents(&coverage, &validComponentFlags);
+ }
+ return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
+}
+
//////////////////////////////////////////////////////////////////////////////
GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
@@ -323,6 +456,22 @@ GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawS
//////////////////////////////////////////////////////////////////////////////s
+bool GrDrawState::willEffectReadDstColor() const {
+ if (!this->isColorWriteDisabled()) {
+ for (int s = 0; s < this->numColorStages(); ++s) {
+ if (this->getColorStage(s).getFragmentProcessor()->willReadDstColor()) {
+ return true;
+ }
+ }
+ }
+ for (int s = 0; s < this->numCoverageStages(); ++s) {
+ if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
+ return true;
+ }
+ }
+ return false;
+}
+
void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
if (fDrawState) {
// See the big comment on the class definition about GPs.
@@ -360,6 +509,28 @@ void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
////////////////////////////////////////////////////////////////////////////////
+// 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();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
void GrDrawState::AutoViewMatrixRestore::restore() {
if (fDrawState) {
SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
@@ -462,6 +633,22 @@ void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& co
////////////////////////////////////////////////////////////////////////////////
+void GrDrawState::convertToPendingExec() {
+ fRenderTarget.markPendingIO();
+ fRenderTarget.removeRef();
+ for (int i = 0; i < fColorStages.count(); ++i) {
+ fColorStages[i].convertToPendingExec();
+ }
+ if (fGeometryProcessor) {
+ fGeometryProcessor->convertToPendingExec();
+ }
+ for (int i = 0; i < fCoverageStages.count(); ++i) {
+ fCoverageStages[i].convertToPendingExec();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
void GrDrawState::invalidateOptState() const {
SkSafeSetNull(fCachedOptState);
}
@@ -473,3 +660,150 @@ GrDrawState::~GrDrawState() {
SkASSERT(0 == fBlockEffectRemovalCnt);
}
+////////////////////////////////////////////////////////////////////////////////
+
+GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
+ GrBlendCoeff* srcCoeff,
+ GrBlendCoeff* dstCoeff) const {
+ GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
+ if (NULL == srcCoeff) {
+ srcCoeff = &bogusSrcCoeff;
+ }
+ if (NULL == dstCoeff) {
+ dstCoeff = &bogusDstCoeff;
+ }
+
+ *srcCoeff = this->getSrcBlendCoeff();
+ *dstCoeff = this->getDstBlendCoeff();
+
+ if (this->isColorWriteDisabled()) {
+ *srcCoeff = kZero_GrBlendCoeff;
+ *dstCoeff = kOne_GrBlendCoeff;
+ }
+
+ bool srcAIsOne = this->srcAlphaWillBeOne();
+ bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
+ (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
+ bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
+ (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
+
+ // 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).
+ if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
+ if (this->getStencil().doesWrite()) {
+ return kEmitCoverage_BlendOptFlag;
+ } else {
+ *dstCoeff = kOne_GrBlendCoeff;
+ return kSkipDraw_BlendOptFlag;
+ }
+ }
+
+ 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.
+ if (!hasCoverage) {
+ if (dstCoeffIsZero) {
+ if (kOne_GrBlendCoeff == *srcCoeff) {
+ // if there is no coverage and coeffs are (1,0) then we
+ // won't need to read the dst at all, it gets replaced by src
+ *dstCoeff = kZero_GrBlendCoeff;
+ return kNone_BlendOpt;
+ } else if (kZero_GrBlendCoeff == *srcCoeff) {
+ // if the op is "clear" then we don't need to emit a color
+ // or blend, just write transparent black into the dst.
+ *srcCoeff = kOne_GrBlendCoeff;
+ *dstCoeff = kZero_GrBlendCoeff;
+ return kEmitTransBlack_BlendOptFlag;
+ }
+ }
+ } else if (this->isCoverageDrawing()) {
+ // we have coverage but we aren't distinguishing it from alpha by request.
+ return kCoverageAsAlpha_BlendOptFlag;
+ } else {
+ // check whether coverage can be safely rolled into alpha
+ // of if we can skip color computation and just emit coverage
+ if (this->canTweakAlphaForCoverage()) {
+ return kCoverageAsAlpha_BlendOptFlag;
+ }
+ if (dstCoeffIsZero) {
+ if (kZero_GrBlendCoeff == *srcCoeff) {
+ // the source color is not included in the blend
+ // the dst coeff is effectively zero so blend works out to:
+ // (c)(0)D + (1-c)D = (1-c)D.
+ *dstCoeff = kISA_GrBlendCoeff;
+ return kEmitCoverage_BlendOptFlag;
+ } else if (srcAIsOne) {
+ // the dst coeff is effectively zero so blend works out to:
+ // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
+ // If Sa is 1 then we can replace Sa with c
+ // and set dst coeff to 1-Sa.
+ *dstCoeff = kISA_GrBlendCoeff;
+ return kCoverageAsAlpha_BlendOptFlag;
+ }
+ } else if (dstCoeffIsOne) {
+ // the dst coeff is effectively one so blend works out to:
+ // cS + (c)(1)D + (1-c)D = cS + D.
+ *dstCoeff = kOne_GrBlendCoeff;
+ return kCoverageAsAlpha_BlendOptFlag;
+ }
+ }
+
+ return kNone_BlendOpt;
+}
+
+
+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 GrProcessor* processor = this->getColorStage(s).getProcessor();
+ processor->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 GrProcessor* processor = this->getCoverageStage(s).getProcessor();
+ processor->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);
+}
+
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 19ea4df8c3..b855c8725b 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -8,21 +8,22 @@
#ifndef GrDrawState_DEFINED
#define GrDrawState_DEFINED
+
#include "GrBlend.h"
#include "GrDrawTargetCaps.h"
#include "GrGpuResourceRef.h"
-#include "GrRODrawState.h"
+#include "GrProcessorStage.h"
+#include "GrRenderTarget.h"
+#include "GrStencil.h"
+#include "SkMatrix.h"
#include "effects/GrSimpleTextureEffect.h"
+class GrDrawTargetCaps;
class GrOptDrawState;
+class GrPaint;
+class GrTexture;
-/**
- * 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 {
+class GrDrawState : public SkRefCnt {
public:
SK_DECLARE_INST_COUNT(GrDrawState)
@@ -70,6 +71,31 @@ public:
/// @name Vertex Attributes
////
+ enum {
+ kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
+ };
+
+ const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
+ int getVertexAttribCount() const { return fVACount; }
+
+ size_t getVertexStride() const { return fVAStride; }
+
+ bool hasLocalCoordAttribute() const {
+ return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
+ }
+ bool hasColorVertexAttribute() const {
+ return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
+ }
+ bool hasCoverageVertexAttribute() const {
+ return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
+ }
+
+ const int* getFixedFunctionVertexAttribIndices() const {
+ return fFixedFunctionVertexAttribIndices;
+ }
+
+ bool validateVertexAttribs() const;
+
/**
* 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
@@ -127,12 +153,19 @@ public:
*/
bool couldApplyCoverage(const GrDrawTargetCaps& caps) 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; }
+
/**
* Sets color for next draw to a premultiplied-alpha color.
*
@@ -159,6 +192,12 @@ public:
/// @name Coverage
////
+ uint8_t getCoverage() const { return fCoverage; }
+
+ GrColor getCoverageColor() const {
+ return GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
+ }
+
/**
* Sets a constant fractional coverage to be applied to the draw. The
* initial value (after construction or reset()) is 0xff. The constant
@@ -207,6 +246,23 @@ public:
/// the color / coverage distinction.
////
+ int numColorStages() const { return fColorStages.count(); }
+ int numCoverageStages() const { return fCoverageStages.count(); }
+ int numTotalStages() const {
+ return this->numColorStages() + this->numCoverageStages() +
+ (this->hasGeometryProcessor() ? 1 : 0);
+ }
+
+ bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
+ const GrGeometryStage* getGeometryProcessor() const { return fGeometryProcessor.get(); }
+ const GrFragmentStage& getColorStage(int idx) const { return fColorStages[idx]; }
+ const GrFragmentStage& getCoverageStage(int idx) const { return fCoverageStages[idx]; }
+
+ /**
+ * Checks whether any of the effects will read the dst pixel color.
+ */
+ bool willEffectReadDstColor() const;
+
const GrFragmentProcessor* addColorProcessor(const GrFragmentProcessor* effect) {
SkASSERT(effect);
SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (effect));
@@ -295,6 +351,22 @@ public:
/// @name Blending
////
+ GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
+ GrBlendCoeff getDstBlendCoeff() const { return 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;
+
/**
* Sets the blending function coefficients.
*
@@ -348,6 +420,32 @@ public:
////
/**
+ * 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 {
+ SkMatrix inverse;
+ if (fViewMatrix.invert(&inverse)) {
+ if (matrix) {
+ *matrix = inverse;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Sets the view matrix to identity and updates any installed effects to compensate for the
* coord system change.
*/
@@ -398,6 +496,15 @@ public:
////
/**
+ * Retrieves the currently set render-target.
+ *
+ * @return The currently set render target.
+ */
+ GrRenderTarget* getRenderTarget() const {
+ return static_cast<GrRenderTarget*>(fRenderTarget.getResource());
+ }
+
+ /**
* Sets the render-target used at the next drawing call
*
* @param target The render target to set.
@@ -413,6 +520,8 @@ public:
/// @name Stencil
////
+ const GrStencilSettings& getStencil() const { return fStencilSettings; }
+
/**
* Sets the stencil settings to use for the next draw.
* Changing the clip has the side-effect of possibly zeroing
@@ -445,6 +554,54 @@ 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,
+ };
+
+ uint32_t getFlagBits() const { return fFlagBits; }
+
+ bool isStateFlagEnabled(uint32_t stateBit) const { return 0 != (stateBit & fFlagBits); }
+
+ bool isClipState() const { return 0 != (fFlagBits & kClip_StateBit); }
+ bool isColorWriteDisabled() const { return 0 != (fFlagBits & kNoColorWrites_StateBit); }
+ bool isCoverageDrawing() const { return 0 != (fFlagBits & kCoverageDrawing_StateBit); }
+
void resetStateFlags() {
if (0 != fFlagBits) {
fFlagBits = 0;
@@ -496,6 +653,21 @@ public:
/// @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; }
+
/**
* Controls whether clockwise, counterclockwise, or both faces are drawn.
* @param face the face(s) to draw.
@@ -512,8 +684,12 @@ public:
/// Hints that when provided can enable optimizations.
////
+ enum Hints { kVertexColorsAreOpaque_Hint = 0x1, };
+
void setHint(Hints hint, bool value) { fHints = value ? (fHints | hint) : (fHints & ~hint); }
+ bool vertexColorsAreOpaque() const { return kVertexColorsAreOpaque_Hint & fHints; }
+
/// @}
///////////////////////////////////////////////////////////////////////////
@@ -548,6 +724,71 @@ public:
GrOptDrawState* createOptState(const GrDrawTargetCaps&) const;
private:
+ /**
+ * Converts refs on GrGpuResources owned directly or indirectly by this GrDrawState into
+ * pending reads and writes. This should be called when a GrDrawState is recorded into
+ * a GrDrawTarget for later execution. Subclasses of GrDrawState may add setters. However,
+ * once this call has been made the GrDrawState is immutable. It is also no longer copyable.
+ * In the future this conversion will automatically happen when converting a GrDrawState into
+ * an optimized draw state.
+ */
+ void convertToPendingExec();
+
+ friend class GrDrawTarget;
+
+ bool isEqual(const GrDrawState& that) 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,
+ };
+ GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
+
+ /**
+ * 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
+ * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
+ * determine the blend optimizations that would be used if there was partial pixel coverage.
+ *
+ * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
+ * playback) must call this function and respect the flags that replace the output color.
+ *
+ * If the cached BlendOptFlags does not have the invalidate bit set, then getBlendOpts will
+ * simply returned the cached flags and coefficients. Otherwise it will calculate the values.
+ */
+ BlendOptFlags getBlendOpts(bool forceCoverage = false,
+ GrBlendCoeff* srcCoeff = NULL,
+ GrBlendCoeff* dstCoeff = NULL) const;
+
+ /**
+ * Determines whether src alpha is guaranteed to be one for all src pixels
+ */
+ bool srcAlphaWillBeOne() const;
+
void invalidateOptState() const;
void onReset(const SkMatrix* initialViewMatrix);
@@ -558,10 +799,39 @@ private:
void internalSetVertexAttribs(const GrVertexAttrib attribs[], int count, size_t stride);
+ typedef GrTGpuResourceRef<GrRenderTarget> ProgramRenderTarget;
+ // These fields are roughly sorted by decreasing likelihood of being different in op==
+ ProgramRenderTarget fRenderTarget;
+ GrColor fColor;
+ SkMatrix fViewMatrix;
+ GrColor fBlendConstant;
+ uint32_t fFlagBits;
+ const GrVertexAttrib* fVAPtr;
+ int fVACount;
+ size_t fVAStride;
+ GrStencilSettings fStencilSettings;
+ uint8_t fCoverage;
+ DrawFace fDrawFace;
+ GrBlendCoeff fSrcBlend;
+ GrBlendCoeff fDstBlend;
+
+ typedef SkSTArray<4, GrFragmentStage> FragmentStageArray;
+ SkAutoTDelete<GrGeometryStage> fGeometryProcessor;
+ FragmentStageArray fColorStages;
+ FragmentStageArray fCoverageStages;
+
+ uint32_t fHints;
+
+ // This is simply a different representation of info in fVertexAttribs and thus does
+ // not need to be compared in op==.
+ int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
+
mutable GrOptDrawState* fCachedOptState;
mutable uint32_t fCachedCapsID;
- typedef GrRODrawState INHERITED;
+ typedef SkRefCnt INHERITED;
};
+//GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
+
#endif
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index 8ffc681627..dd2224bdbd 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -694,8 +694,8 @@ public:
virtual DrawToken getCurrentDrawToken() { return DrawToken(this, 0); }
protected:
- // Extend access to GrRODrawState::convertToPEndeingExec to subclasses.
- void convertDrawStateToPendingExec(GrRODrawState* ds) {
+ // Extend access to GrDrawState::convertToPEndeingExec to subclasses.
+ void convertDrawStateToPendingExec(GrDrawState* ds) {
ds->convertToPendingExec();
}
diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp
index 8653a8bd2c..98a5689d53 100644
--- a/src/gpu/GrOptDrawState.cpp
+++ b/src/gpu/GrOptDrawState.cpp
@@ -15,7 +15,9 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
BlendOptFlags blendOptFlags,
GrBlendCoeff optSrcCoeff,
GrBlendCoeff optDstCoeff,
- const GrDrawTargetCaps& caps) : INHERITED(drawState) {
+ const GrDrawTargetCaps& caps) {
+ fRenderTarget.set(SkSafeRef(drawState.getRenderTarget()),
+ GrIORef::kWrite_IOType);
fColor = drawState.getColor();
fCoverage = drawState.getCoverage();
fViewMatrix = drawState.getViewMatrix();
@@ -25,14 +27,14 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
fVACount = drawState.getVertexAttribCount();
fVAStride = drawState.getVertexStride();
fStencilSettings = drawState.getStencil();
- fDrawFace = drawState.getDrawFace();
+ fDrawFace = (DrawFace)drawState.getDrawFace();
fBlendOptFlags = blendOptFlags;
fSrcBlend = optSrcCoeff;
fDstBlend = optDstCoeff;
memcpy(fFixedFunctionVertexAttribIndices,
- drawState.getFixedFunctionVertexAttribIndices(),
- sizeof(fFixedFunctionVertexAttribIndices));
+ drawState.getFixedFunctionVertexAttribIndices(),
+ sizeof(fFixedFunctionVertexAttribIndices));
fInputColorIsUsed = true;
@@ -262,7 +264,76 @@ void GrOptDrawState::getStageStats() {
}
}
+////////////////////////////////////////////////////////////////////////////////
+
bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
return this->isEqual(that);
}
+bool GrOptDrawState::isEqual(const GrOptDrawState& that) const {
+ bool usingVertexColors = this->hasColorVertexAttribute();
+ if (!usingVertexColors && this->fColor != that.fColor) {
+ return false;
+ }
+
+ if (this->getRenderTarget() != that.getRenderTarget() ||
+ 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 ||
+ this->fVAStride != that.fVAStride ||
+ memcmp(this->fVAPtr, that.fVAPtr, this->fVACount * sizeof(GrVertexAttrib)) ||
+ this->fStencilSettings != that.fStencilSettings ||
+ this->fDrawFace != that.fDrawFace ||
+ this->fInputColorIsUsed != that.fInputColorIsUsed ||
+ this->fInputCoverageIsUsed != that.fInputCoverageIsUsed ||
+ this->fReadsDst != that.fReadsDst ||
+ this->fReadsFragPosition != that.fReadsFragPosition ||
+ this->fRequiresLocalCoordAttrib != that.fRequiresLocalCoordAttrib ||
+ this->fPrimaryOutputType != that.fPrimaryOutputType ||
+ this->fSecondaryOutputType != that.fSecondaryOutputType) {
+ return false;
+ }
+
+ bool usingVertexCoverage = this->hasCoverageVertexAttribute();
+ if (!usingVertexCoverage && this->fCoverage != that.fCoverage) {
+ return false;
+ }
+
+ bool explicitLocalCoords = this->hasLocalCoordAttribute();
+ if (this->hasGeometryProcessor()) {
+ if (!that.hasGeometryProcessor()) {
+ return false;
+ } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
+ *that.getGeometryProcessor(),
+ explicitLocalCoords)) {
+ return false;
+ }
+ } else if (that.hasGeometryProcessor()) {
+ return false;
+ }
+
+ for (int i = 0; i < this->numColorStages(); i++) {
+ if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
+ explicitLocalCoords)) {
+ return false;
+ }
+ }
+ for (int i = 0; i < this->numCoverageStages(); i++) {
+ if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
+ explicitLocalCoords)) {
+ return false;
+ }
+ }
+
+ SkASSERT(0 == memcmp(this->fFixedFunctionVertexAttribIndices,
+ that.fFixedFunctionVertexAttribIndices,
+ sizeof(this->fFixedFunctionVertexAttribIndices)));
+
+ return true;
+}
+
diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h
index b4f59d3a7b..f0a726e954 100644
--- a/src/gpu/GrOptDrawState.h
+++ b/src/gpu/GrOptDrawState.h
@@ -9,17 +9,272 @@
#define GrOptDrawState_DEFINED
#include "GrDrawState.h"
-#include "GrRODrawState.h"
/**
- * Subclass of GrRODrawState that holds an optimized version of a GrDrawState. Like it's parent
- * it is meant to be an immutable class, and simply adds a few helpful data members not in the
- * base class.
+ * Class that holds an optimized version of a GrDrawState. It is meant to be an immutable class,
+ * and contains all data needed to set the state for a gpu draw.
*/
-class GrOptDrawState : public GrRODrawState {
+class GrOptDrawState : public SkRefCnt {
public:
bool operator== (const GrOptDrawState& that) const;
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Vertex Attributes
+ ////
+
+ enum {
+ kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
+ };
+
+ const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
+ int getVertexAttribCount() const { return fVACount; }
+
+ size_t getVertexStride() const { return fVAStride; }
+
+ /**
+ * 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];
+ }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @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 GrProcessor. 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() +
+ (this->hasGeometryProcessor() ? 1 : 0);
+ }
+
+ bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
+ const GrGeometryStage* getGeometryProcessor() const { return fGeometryProcessor.get(); }
+ const GrFragmentStage& getColorStage(int idx) const { return fColorStages[idx]; }
+ const GrFragmentStage& getCoverageStage(int idx) const { return fCoverageStages[idx]; }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @name Blending
+ ////
+
+ GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
+ GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
+
+ /**
+ * Retrieves the last value set by setBlendConstant()
+ * @return the blending constant value
+ */
+ GrColor getBlendConstant() const { return fBlendConstant; }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @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 {
+ 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.
+ */
+ GrRenderTarget* getRenderTarget() const {
+ return static_cast<GrRenderTarget*>(fRenderTarget.getResource());
+ }
+
+ /// @}
+
+ ///////////////////////////////////////////////////////////////////////////
+ /// @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,
+ };
+
bool inputColorIsUsed() const { return fInputColorIsUsed; }
bool inputCoverageIsUsed() const { return fInputCoverageIsUsed; }
@@ -64,6 +319,35 @@ public:
private:
/**
+ * 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,
+ };
+ GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
+
+ /**
* Constructs and optimized drawState out of a GrRODrawState.
*/
GrOptDrawState(const GrDrawState& drawState, BlendOptFlags blendOptFlags,
@@ -114,6 +398,33 @@ private:
*/
void setOutputStateInfo(const GrDrawTargetCaps&);
+ bool isEqual(const GrOptDrawState& that) const;
+
+ // These fields are roughly sorted by decreasing likelihood of being different in op==
+ typedef GrTGpuResourceRef<GrRenderTarget> ProgramRenderTarget;
+ ProgramRenderTarget fRenderTarget;
+ GrColor fColor;
+ SkMatrix fViewMatrix;
+ GrColor fBlendConstant;
+ uint32_t fFlagBits;
+ const GrVertexAttrib* fVAPtr;
+ int fVACount;
+ size_t fVAStride;
+ GrStencilSettings fStencilSettings;
+ uint8_t fCoverage;
+ DrawFace fDrawFace;
+ GrBlendCoeff fSrcBlend;
+ GrBlendCoeff fDstBlend;
+
+ typedef SkSTArray<4, GrFragmentStage> FragmentStageArray;
+ SkAutoTDelete<GrGeometryStage> fGeometryProcessor;
+ FragmentStageArray fColorStages;
+ FragmentStageArray fCoverageStages;
+
+ // This is simply a different representation of info in fVertexAttribs and thus does
+ // not need to be compared in op==.
+ int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
+
// These flags are needed to protect the code from creating an unused uniform color/coverage
// which will cause shader compiler errors.
bool fInputColorIsUsed;
@@ -133,7 +444,10 @@ private:
SecondaryOutputType fSecondaryOutputType : 8;
friend GrOptDrawState* GrDrawState::createOptState(const GrDrawTargetCaps&) const;
- typedef GrRODrawState INHERITED;
+ typedef SkRefCnt INHERITED;
};
+GR_MAKE_BITFIELD_OPS(GrOptDrawState::BlendOptFlags);
+
#endif
+
diff --git a/src/gpu/GrRODrawState.cpp b/src/gpu/GrRODrawState.cpp
deleted file mode 100644
index 2a673f3e5e..0000000000
--- a/src/gpu/GrRODrawState.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * 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"
-#include "GrRenderTarget.h"
-
-////////////////////////////////////////////////////////////////////////////////
-
-GrRODrawState::GrRODrawState(const GrRODrawState& drawState) : INHERITED() {
- fRenderTarget.setResource(SkSafeRef(drawState.fRenderTarget.getResource()),
- GrIORef::kWrite_IOType);
-}
-
-bool GrRODrawState::isEqual(const GrRODrawState& that) const {
- bool usingVertexColors = this->hasColorVertexAttribute();
- if (!usingVertexColors && this->fColor != that.fColor) {
- return false;
- }
-
- if (this->getRenderTarget() != that.getRenderTarget() ||
- 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 ||
- this->fVAStride != that.fVAStride ||
- 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();
- if (this->hasGeometryProcessor()) {
- if (!that.hasGeometryProcessor()) {
- return false;
- } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
- *that.getGeometryProcessor(),
- explicitLocalCoords)) {
- return false;
- }
- } else if (that.hasGeometryProcessor()) {
- return false;
- }
-
- for (int i = 0; i < this->numColorStages(); i++) {
- if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
- explicitLocalCoords)) {
- return false;
- }
- }
- for (int i = 0; i < this->numCoverageStages(); i++) {
- if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
- explicitLocalCoords)) {
- return false;
- }
- }
-
- 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);
- }
-
- if (this->hasGeometryProcessor()) {
- const GrGeometryStage& stage = *this->getGeometryProcessor();
- const GrGeometryProcessor* gp = stage.getGeometryProcessor();
- SkASSERT(gp);
- // 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 GrGeometryProcessor::VertexAttribArray& s = gp->getVertexAttribs();
-
- int effectIndex = 0;
- for (int index = 0; index < fVACount; index++) {
- if (kGeometryProcessor_GrVertexAttribBinding != fVAPtr[index].fBinding) {
- // we only care about effect bindings
- continue;
- }
- SkASSERT(effectIndex < s.count());
- GrSLType effectSLType = s[effectIndex].getType();
- GrVertexAttribType attribType = fVAPtr[index].fType;
- int slVecCount = GrSLTypeVectorCount(effectSLType);
- int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
- if (slVecCount != attribVecCount ||
- (static_cast<GrSLType>(-1) != slTypes[index] && slTypes[index] != effectSLType)) {
- return false;
- }
- slTypes[index] = effectSLType;
- effectIndex++;
- }
- // Make sure all attributes are consumed and we were able to find everything
- SkASSERT(s.count() == effectIndex);
- }
-
- 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.
- if (this->hasGeometryProcessor()) {
- const GrGeometryProcessor* gp = fGeometryProcessor->getGeometryProcessor();
- gp->getConstantColorComponents(&coverage, &validComponentFlags);
- }
- for (int s = 0; s < this->numCoverageStages(); ++s) {
- const GrProcessor* processor = this->getCoverageStage(s).getProcessor();
- processor->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).getFragmentProcessor()->willReadDstColor()) {
- return true;
- }
- }
- }
- for (int s = 0; s < this->numCoverageStages(); ++s) {
- if (this->getCoverageStage(s).getFragmentProcessor()->willReadDstColor()) {
- return true;
- }
- }
- return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-GrRODrawState::BlendOptFlags GrRODrawState::getBlendOpts(bool forceCoverage,
- GrBlendCoeff* srcCoeff,
- GrBlendCoeff* dstCoeff) const {
- GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
- if (NULL == srcCoeff) {
- srcCoeff = &bogusSrcCoeff;
- }
- if (NULL == dstCoeff) {
- dstCoeff = &bogusDstCoeff;
- }
-
- *srcCoeff = this->getSrcBlendCoeff();
- *dstCoeff = this->getDstBlendCoeff();
-
- if (this->isColorWriteDisabled()) {
- *srcCoeff = kZero_GrBlendCoeff;
- *dstCoeff = kOne_GrBlendCoeff;
- }
-
- bool srcAIsOne = this->srcAlphaWillBeOne();
- bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
- (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
- bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
- (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
-
- // 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).
- if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne)) {
- if (this->getStencil().doesWrite()) {
- return kEmitCoverage_BlendOptFlag;
- } else {
- *dstCoeff = kOne_GrBlendCoeff;
- return kSkipDraw_BlendOptFlag;
- }
- }
-
- 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.
- if (!hasCoverage) {
- if (dstCoeffIsZero) {
- if (kOne_GrBlendCoeff == *srcCoeff) {
- // if there is no coverage and coeffs are (1,0) then we
- // won't need to read the dst at all, it gets replaced by src
- *dstCoeff = kZero_GrBlendCoeff;
- return kNone_BlendOpt;
- } else if (kZero_GrBlendCoeff == *srcCoeff) {
- // if the op is "clear" then we don't need to emit a color
- // or blend, just write transparent black into the dst.
- *srcCoeff = kOne_GrBlendCoeff;
- *dstCoeff = kZero_GrBlendCoeff;
- return kEmitTransBlack_BlendOptFlag;
- }
- }
- } else if (this->isCoverageDrawing()) {
- // we have coverage but we aren't distinguishing it from alpha by request.
- return kCoverageAsAlpha_BlendOptFlag;
- } else {
- // check whether coverage can be safely rolled into alpha
- // of if we can skip color computation and just emit coverage
- if (this->canTweakAlphaForCoverage()) {
- return kCoverageAsAlpha_BlendOptFlag;
- }
- if (dstCoeffIsZero) {
- if (kZero_GrBlendCoeff == *srcCoeff) {
- // the source color is not included in the blend
- // the dst coeff is effectively zero so blend works out to:
- // (c)(0)D + (1-c)D = (1-c)D.
- *dstCoeff = kISA_GrBlendCoeff;
- return kEmitCoverage_BlendOptFlag;
- } else if (srcAIsOne) {
- // the dst coeff is effectively zero so blend works out to:
- // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
- // If Sa is 1 then we can replace Sa with c
- // and set dst coeff to 1-Sa.
- *dstCoeff = kISA_GrBlendCoeff;
- return kCoverageAsAlpha_BlendOptFlag;
- }
- } else if (dstCoeffIsOne) {
- // the dst coeff is effectively one so blend works out to:
- // cS + (c)(1)D + (1-c)D = cS + D.
- *dstCoeff = kOne_GrBlendCoeff;
- return kCoverageAsAlpha_BlendOptFlag;
- }
- }
-
- return kNone_BlendOpt;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-// 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();
-}
-
-void GrRODrawState::convertToPendingExec() {
- fRenderTarget.markPendingIO();
- fRenderTarget.removeRef();
- for (int i = 0; i < fColorStages.count(); ++i) {
- fColorStages[i].convertToPendingExec();
- }
- if (fGeometryProcessor) {
- fGeometryProcessor->convertToPendingExec();
- }
- for (int i = 0; i < fCoverageStages.count(); ++i) {
- fCoverageStages[i].convertToPendingExec();
- }
-}
-
-bool GrRODrawState::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 GrProcessor* processor = this->getColorStage(s).getProcessor();
- processor->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 GrProcessor* processor = this->getCoverageStage(s).getProcessor();
- processor->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);
-}
-
diff --git a/src/gpu/GrRODrawState.h b/src/gpu/GrRODrawState.h
deleted file mode 100644
index ac263ff812..0000000000
--- a/src/gpu/GrRODrawState.h
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * 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 "GrProcessorStage.h"
-#include "GrRenderTarget.h"
-#include "GrStencil.h"
-#include "SkMatrix.h"
-
-class GrDrawState;
-class GrDrawTargetCaps;
-class GrPaint;
-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)
-
- GrRODrawState() {}
-
- GrRODrawState& operator= (const GrRODrawState& that);
-
- ///////////////////////////////////////////////////////////////////////////
- /// @name Vertex Attributes
- ////
-
- enum {
- kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
- };
-
- const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
- int getVertexAttribCount() const { return fVACount; }
-
- size_t getVertexStride() const { return fVAStride; }
-
- /**
- * 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];
- }
-
- const int* getFixedFunctionVertexAttribIndices() const {
- return fFixedFunctionVertexAttribIndices;
- }
-
- 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 GrProcessor. 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() +
- (this->hasGeometryProcessor() ? 1 : 0);
- }
-
- bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
- const GrGeometryStage* getGeometryProcessor() const { return fGeometryProcessor.get(); }
- const GrFragmentStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
- const GrFragmentStage& 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;
-
- /// @}
-
- ///////////////////////////////////////////////////////////////////////////
- /// @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.
- */
- GrRenderTarget* getRenderTarget() const {
- return static_cast<GrRenderTarget*>(fRenderTarget.getResource());
- }
-
- /// @}
-
- ///////////////////////////////////////////////////////////////////////////
- /// @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,
- };
-
- uint32_t getFlagBits() const { return fFlagBits; }
-
- 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; }
-
- /// @}
-
- ///////////////////////////////////////////////////////////////////////////
- /// @name Hints
- /// Hints that when provided can enable optimizations.
- ////
-
- enum Hints { kVertexColorsAreOpaque_Hint = 0x1, };
-
- bool vertexColorsAreOpaque() const { return kVertexColorsAreOpaque_Hint & fHints; }
-
- /// @}
-
- ///////////////////////////////////////////////////////////////////////////
-
- /** 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,
- };
-
-protected:
- /**
- * Converts refs on GrGpuResources owned directly or indirectly by this GrRODrawState into
- * pending reads and writes. This should be called when a GrDrawState is recorded into
- * a GrDrawTarget for later execution. Subclasses of GrRODrawState may add setters. However,
- * once this call has been made the GrRODrawState is immutable. It is also no longer copyable.
- * In the future this conversion will automatically happen when converting a GrDrawState into
- * an optimized draw state.
- */
- void convertToPendingExec();
-
- friend class GrDrawTarget;
-
- explicit GrRODrawState(const GrRODrawState& drawState);
-
- bool isEqual(const GrRODrawState& that) 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,
- };
- GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
-
- /**
- * 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
- * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
- * determine the blend optimizations that would be used if there was partial pixel coverage.
- *
- * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
- * playback) must call this function and respect the flags that replace the output color.
- *
- * If the cached BlendOptFlags does not have the invalidate bit set, then getBlendOpts will
- * simply returned the cached flags and coefficients. Otherwise it will calculate the values.
- */
- BlendOptFlags getBlendOpts(bool forceCoverage = false,
- GrBlendCoeff* srcCoeff = NULL,
- GrBlendCoeff* dstCoeff = NULL) const;
-
- typedef GrTGpuResourceRef<GrRenderTarget> ProgramRenderTarget;
- // These fields are roughly sorted by decreasing likelihood of being different in op==
- ProgramRenderTarget fRenderTarget;
- GrColor fColor;
- SkMatrix fViewMatrix;
- GrColor fBlendConstant;
- uint32_t fFlagBits;
- const GrVertexAttrib* fVAPtr;
- int fVACount;
- size_t fVAStride;
- GrStencilSettings fStencilSettings;
- uint8_t fCoverage;
- DrawFace fDrawFace;
- GrBlendCoeff fSrcBlend;
- GrBlendCoeff fDstBlend;
-
- typedef SkSTArray<4, GrFragmentStage> FragmentStageArray;
- SkAutoTDelete<GrGeometryStage> fGeometryProcessor;
- FragmentStageArray fColorStages;
- FragmentStageArray fCoverageStages;
-
- uint32_t fHints;
-
- // This is simply a different representation of info in fVertexAttribs and thus does
- // not need to be compared in op==.
- int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
-
-private:
- /**
- * Determines whether src alpha is guaranteed to be one for all src pixels
- */
- bool srcAlphaWillBeOne() const;
-
- typedef SkRefCnt INHERITED;
-};
-
-GR_MAKE_BITFIELD_OPS(GrRODrawState::BlendOptFlags);
-
-#endif
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index a01f7b74ff..be385110c9 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -239,7 +239,7 @@ void GrGpuGL::onResetContext(uint32_t resetBits) {
GL_CALL(Disable(GR_GL_DEPTH_TEST));
GL_CALL(DepthMask(GR_GL_FALSE));
- fHWDrawFace = GrDrawState::kInvalid_DrawFace;
+ fHWDrawFace = GrOptDrawState::kInvalid_DrawFace;
fHWDitherEnabled = kUnknown_TriState;
if (kGL_GrGLStandard == this->glStandard()) {
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 65816b54a8..e5f2915a24 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -431,7 +431,7 @@ private:
TriState fHWStencilTestEnabled;
- GrDrawState::DrawFace fHWDrawFace;
+ GrOptDrawState::DrawFace fHWDrawFace;
TriState fHWWriteToColor;
TriState fHWDitherEnabled;
uint32_t fHWBoundRenderTargetUniqueID;