diff options
-rw-r--r-- | gyp/gpu.gypi | 2 | ||||
-rw-r--r-- | include/gpu/GrGpuResourceRef.h | 3 | ||||
-rw-r--r-- | src/gpu/GrDrawState.cpp | 342 | ||||
-rw-r--r-- | src/gpu/GrDrawState.h | 288 | ||||
-rw-r--r-- | src/gpu/GrDrawTarget.h | 4 | ||||
-rw-r--r-- | src/gpu/GrOptDrawState.cpp | 79 | ||||
-rw-r--r-- | src/gpu/GrOptDrawState.h | 326 | ||||
-rw-r--r-- | src/gpu/GrRODrawState.cpp | 350 | ||||
-rw-r--r-- | src/gpu/GrRODrawState.h | 438 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 2 |
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; |