diff options
Diffstat (limited to 'src/gpu/GrDrawState.h')
-rw-r--r-- | src/gpu/GrDrawState.h | 305 |
1 files changed, 151 insertions, 154 deletions
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 5b1194d0c2..9d1e64d1fe 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -27,43 +27,21 @@ class GrDrawState : public GrRefCnt { public: SK_DECLARE_INST_COUNT(GrDrawState) - /** - * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a - * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the - * output from the previous enabled stage and a position. The position is either derived from - * the interpolated vertex positions or explicit per-vertex coords, depending upon the - * GrAttribBindings used to draw. - * - * 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 enabled 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. - * - * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's - * GrPaint. Stage GrPaint::kTotalStages is earmarked for use by GrTextContext, GrPathRenderer- - * derived classes, and the rect/oval helper classes. GrPaint::kTotalStages+1 is earmarked for - * clipping by GrClipMaskManager. TODO: replace fixed size array of stages with variable size - * arrays of color and coverage stages. - */ - enum { - kNumStages = GrPaint::kTotalStages + 2, - }; - - GrDrawState() { this->reset(); } + GrDrawState() { + GR_DEBUGCODE(fBlockEffectRemovalCnt = 0;) + this->reset(); + } - GrDrawState(const SkMatrix& initialViewMatrix) { this->reset(initialViewMatrix); } + GrDrawState(const SkMatrix& initialViewMatrix) { + GR_DEBUGCODE(fBlockEffectRemovalCnt = 0;) + this->reset(initialViewMatrix); + } /** * Copies another draw state. **/ GrDrawState(const GrDrawState& state) { + GR_DEBUGCODE(fBlockEffectRemovalCnt = 0;) *this = state; } @@ -71,17 +49,19 @@ public: * Copies another draw state with a preconcat to the view matrix. **/ GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) { + GR_DEBUGCODE(fBlockEffectRemovalCnt = 0;) *this = state; if (!preConcatMatrix.isIdentity()) { - for (int i = 0; i < kNumStages; ++i) { - if (this->isStageEnabled(i)) { - fStages[i].localCoordChange(preConcatMatrix); - } + for (int i = 0; i < fColorStages.count(); ++i) { + fColorStages[i].localCoordChange(preConcatMatrix); + } + for (int i = 0; i < fCoverageStages.count(); ++i) { + fCoverageStages[i].localCoordChange(preConcatMatrix); } } } - virtual ~GrDrawState() { this->disableStages(); } + virtual ~GrDrawState() { GrAssert(0 == fBlockEffectRemovalCnt); } /** * Resets to the default state. GrEffects will be removed from all stages. @@ -93,8 +73,7 @@ public: /** * Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that * GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint - * equivalents are set to default values. GrPaint has fewer stages than GrDrawState. The extra - * GrDrawState stages are disabled. Clipping will be enabled. + * equivalents are set to default values. Clipping will be enabled. */ void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*); @@ -359,90 +338,105 @@ public: /////////////////////////////////////////////////////////////////////////// /// @name Effect Stages + /// Each stage hosts a GrEffect. The effect produces an output color or coverage in the fragment + /// shader. Its inputs are the output from the previous stage as well as some variables + /// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color, + /// the fragment position, local coordinates). + /// + /// The stages are divided into two sets, color-computing and coverage-computing. The final + /// color stage produces the final pixel color. The coverage-computing stages function exactly + /// as the color-computing but the output of the final coverage stage is treated as a fractional + /// pixel coverage rather than as input to the src/dst color blend step. + /// + /// The input color to the first color-stage is either the constant color or interpolated + /// per-vertex colors. The input to the first coverage stage is either a constant coverage + /// (usually full-coverage) or interpolated per-vertex coverage. + /// + /// See the documentation of kCoverageDrawing_StateBit for information about disabling the + /// the color / coverage distinction. //// - const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) { - fStages[stageIdx].setEffect(effect); + const GrEffectRef* addColorEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) { + GrAssert(NULL != effect); + SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1)); return effect; } - const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect, - int attr0, int attr1 = -1) { - fStages[stageIdx].setEffect(effect, attr0, attr1); + const GrEffectRef* addCoverageEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) { + GrAssert(NULL != effect); + SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1)); return effect; } /** * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates. */ - void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) { - GrAssert(!this->getStage(stageIdx).getEffect()); + void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix) { GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix); - this->setEffect(stageIdx, effect)->unref(); + this->addColorEffect(effect)->unref(); } - void createTextureEffect(int stageIdx, - GrTexture* texture, - const SkMatrix& matrix, - const GrTextureParams& params) { - GrAssert(!this->getStage(stageIdx).getEffect()); - GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params); - this->setEffect(stageIdx, effect)->unref(); + + void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix) { + GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix); + this->addCoverageEffect(effect)->unref(); } - bool stagesDisabled() { - for (int i = 0; i < kNumStages; ++i) { - if (NULL != fStages[i].getEffect()) { - return false; - } - } - return true; + void addColorTextureEffect(GrTexture* texture, + const SkMatrix& matrix, + const GrTextureParams& params) { + GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params); + this->addColorEffect(effect)->unref(); } - void disableStage(int stageIdx) { - this->setEffect(stageIdx, NULL); + void addCoverageTextureEffect(GrTexture* texture, + const SkMatrix& matrix, + const GrTextureParams& params) { + GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params); + this->addCoverageEffect(effect)->unref(); } /** - * Release all the GrEffects referred to by this draw state. + * When this object is destroyed it will remove any effects from the draw state that were added + * after its constructor. */ - void disableStages() { - for (int i = 0; i < kNumStages; ++i) { - this->disableStage(i); - } - } - - class AutoStageDisable : public ::GrNoncopyable { + class AutoRestoreEffects : public ::GrNoncopyable { public: - AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {} - ~AutoStageDisable() { + AutoRestoreEffects() : fDrawState(NULL) {} + + AutoRestoreEffects(GrDrawState* ds) : fDrawState(NULL) { this->set(ds); } + + ~AutoRestoreEffects() { this->set(NULL); } + + void set(GrDrawState* ds) { if (NULL != fDrawState) { - fDrawState->disableStages(); + int n = fDrawState->fColorStages.count() - fColorEffectCnt; + GrAssert(n >= 0); + fDrawState->fColorStages.pop_back_n(n); + n = fDrawState->fCoverageStages.count() - fCoverageEffectCnt; + GrAssert(n >= 0); + fDrawState->fCoverageStages.pop_back_n(n); + GR_DEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;) + } + fDrawState = ds; + if (NULL != ds) { + fColorEffectCnt = ds->fColorStages.count(); + fCoverageEffectCnt = ds->fCoverageStages.count(); + GR_DEBUGCODE(++ds->fBlockEffectRemovalCnt;) } } + private: GrDrawState* fDrawState; + int fColorEffectCnt; + int fCoverageEffectCnt; }; - /** - * Returns the current stage by index. - */ - const GrEffectStage& getStage(int stageIdx) const { - GrAssert((unsigned)stageIdx < kNumStages); - return fStages[stageIdx]; - } + int numColorStages() const { return fColorStages.count(); } + int numCoverageStages() const { return fCoverageStages.count(); } + int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); } - /** - * Called when the source coord system is changing. This ensures that effects will see the - * correct local coordinates. oldToNew gives the transformation from the old coord system in - * which the geometry was specified to the new coordinate system from which it will be rendered. - */ - void localCoordChange(const SkMatrix& oldToNew) { - for (int i = 0; i < kNumStages; ++i) { - if (this->isStageEnabled(i)) { - fStages[i].localCoordChange(oldToNew); - } - } - } + const GrEffectStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; } + const GrEffectStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; } /** * Checks whether any of the effects will read the dst pixel color. @@ -452,33 +446,6 @@ public: /// @} /////////////////////////////////////////////////////////////////////////// - /// @name Coverage / Color Stages - //// - - /** - * A common pattern is to compute a color with the initial stages and then - * modulate that color by a coverage value in later stage(s) (AA, mask- - * filters, glyph mask, etc). Color-filters, xfermodes, etc should be - * computed based on the pre-coverage-modulated color. The division of - * stages between color-computing and coverage-computing is specified by - * this method. Initially this is kNumStages (all stages - * are color-computing). - */ - void setFirstCoverageStage(int firstCoverageStage) { - GrAssert((unsigned)firstCoverageStage <= kNumStages); - fCommon.fFirstCoverageStage = firstCoverageStage; - } - - /** - * Gets the index of the first coverage-computing stage. - */ - int getFirstCoverageStage() const { - return fCommon.fFirstCoverageStage; - } - - ///@} - - /////////////////////////////////////////////////////////////////////////// /// @name Blending //// @@ -674,10 +641,12 @@ public: bool setIdentity(GrDrawState* drawState); private: - GrDrawState* fDrawState; - SkMatrix fViewMatrix; - GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages]; - uint32_t fRestoreMask; + void doEffectCoordChanges(const SkMatrix& coordChangeMatrix); + + GrDrawState* fDrawState; + SkMatrix fViewMatrix; + int fNumColorStages; + SkAutoSTArray<8, GrEffectStage::SavedCoordChange> fSavedCoordChanges; }; /// @} @@ -905,21 +874,20 @@ public: /////////////////////////////////////////////////////////////////////////// - bool isStageEnabled(int s) const { - GrAssert((unsigned)s < kNumStages); - return (NULL != fStages[s].getEffect()); - } - bool operator ==(const GrDrawState& s) const { - if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) { + if (fRenderTarget.get() != s.fRenderTarget.get() || + fColorStages.count() != s.fColorStages.count() || + fCoverageStages.count() != s.fCoverageStages.count() || + fCommon != s.fCommon) { return false; } - for (int i = 0; i < kNumStages; i++) { - bool enabled = this->isStageEnabled(i); - if (enabled != s.isStageEnabled(i)) { + for (int i = 0; i < fColorStages.count(); i++) { + if (fColorStages[i] != s.fColorStages[i]) { return false; } - if (enabled && this->fStages[i] != s.fStages[i]) { + } + for (int i = 0; i < fCoverageStages.count(); i++) { + if (fCoverageStages[i] != s.fCoverageStages[i]) { return false; } } @@ -928,21 +896,20 @@ public: bool operator !=(const GrDrawState& s) const { return !(*this == s); } GrDrawState& operator= (const GrDrawState& s) { + GrAssert(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages()); this->setRenderTarget(s.fRenderTarget.get()); fCommon = s.fCommon; - for (int i = 0; i < kNumStages; i++) { - if (s.isStageEnabled(i)) { - this->fStages[i] = s.fStages[i]; - } - } + fColorStages = s.fColorStages; + fCoverageStages = s.fCoverageStages; return *this; } private: void onReset(const SkMatrix* initialViewMatrix) { - - this->disableStages(); + GrAssert(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages()); + fColorStages.reset(); + fCoverageStages.reset(); fRenderTarget.reset(NULL); @@ -959,7 +926,6 @@ private: fCommon.fBlendConstant = 0x0; fCommon.fFlagBits = 0x0; fCommon.fStencilSettings.setDisabled(); - fCommon.fFirstCoverageStage = kNumStages; fCommon.fCoverage = 0xffffffff; fCommon.fColorFilterMode = SkXfermode::kDst_Mode; fCommon.fColorFilterColor = 0x0; @@ -978,7 +944,6 @@ private: const GrVertexAttrib* fVAPtr; int fVACount; GrStencilSettings fStencilSettings; - int fFirstCoverageStage; GrColor fCoverage; SkXfermode::Mode fColorFilterMode; GrColor fColorFilterColor; @@ -998,7 +963,6 @@ private: fVACount == other.fVACount && !memcmp(fVAPtr, other.fVAPtr, fVACount * sizeof(GrVertexAttrib)) && fStencilSettings == other.fStencilSettings && - fFirstCoverageStage == other.fFirstCoverageStage && fCoverage == other.fCoverage && fColorFilterMode == other.fColorFilterMode && fColorFilterColor == other.fColorFilterColor && @@ -1042,8 +1006,13 @@ public: // Here we ref the effects directly rather than the effect-refs. TODO: When the effect- // ref gets fully unref'ed it will cause the underlying effect to unref its resources // and recycle them to the cache (if no one else is holding a ref to the resources). - for (int i = 0; i < kNumStages; ++i) { - fStages[i].saveFrom(drawState.fStages[i]); + fStages.reset(drawState.fColorStages.count() + drawState.fCoverageStages.count()); + fColorStageCnt = drawState.fColorStages.count(); + for (int i = 0; i < fColorStageCnt; ++i) { + fStages[i].saveFrom(drawState.fColorStages[i]); + } + for (int i = 0; i < drawState.fCoverageStages.count(); ++i) { + fStages[i + fColorStageCnt].saveFrom(drawState.fCoverageStages[i]); } GR_DEBUGCODE(fInitialized = true;) } @@ -1052,17 +1021,35 @@ public: GrAssert(fInitialized); drawState->fCommon = fCommon; drawState->setRenderTarget(fRenderTarget); - for (int i = 0; i < kNumStages; ++i) { - fStages[i].restoreTo(&drawState->fStages[i]); + // reinflate color/cov stage arrays. + drawState->fColorStages.reset(fColorStageCnt); + for (int i = 0; i < fColorStageCnt; ++i) { + fStages[i].restoreTo(&drawState->fColorStages[i]); + } + int coverageStageCnt = fStages.count() - fColorStageCnt; + drawState->fCoverageStages.reset(coverageStageCnt); + for (int i = 0; i < coverageStageCnt; ++i) { + fStages[fColorStageCnt + i].restoreTo(&drawState->fCoverageStages[i]); } } bool isEqual(const GrDrawState& state) const { - if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) { + int numCoverageStages = fStages.count() - fColorStageCnt; + if (fRenderTarget != state.fRenderTarget.get() || + fColorStageCnt != state.fColorStages.count() || + numCoverageStages != state.fCoverageStages.count() || + fCommon != state.fCommon) { return false; } - for (int i = 0; i < kNumStages; ++i) { - if (!fStages[i].isEqual(state.fStages[i], state.hasLocalCoordAttribute())) { + bool explicitLocalCoords = state.hasLocalCoordAttribute(); + for (int i = 0; i < fColorStageCnt; ++i) { + if (!fStages[i].isEqual(state.fColorStages[i], explicitLocalCoords)) { + return false; + } + } + for (int i = 0; i < numCoverageStages; ++i) { + int s = fColorStageCnt + i; + if (!fStages[s].isEqual(state.fCoverageStages[i], explicitLocalCoords)) { return false; } } @@ -1070,18 +1057,28 @@ public: } private: + typedef SkAutoSTArray<8, GrEffectStage::DeferredStage> DeferredStageArray; + GrRenderTarget* fRenderTarget; CommonState fCommon; - GrEffectStage::DeferredStage fStages[kNumStages]; + int fColorStageCnt; + DeferredStageArray fStages; GR_DEBUGCODE(bool fInitialized;) }; private: - SkAutoTUnref<GrRenderTarget> fRenderTarget; - CommonState fCommon; - GrEffectStage fStages[kNumStages]; + SkAutoTUnref<GrRenderTarget> fRenderTarget; + CommonState fCommon; + + typedef SkSTArray<4, GrEffectStage> EffectStageArray; + EffectStageArray fColorStages; + EffectStageArray fCoverageStages; + + // Some of the auto restore objects assume that no effects are removed during their lifetime. + // This is used to assert that this condition holds. + GR_DEBUGCODE(int fBlockEffectRemovalCnt;) /** * Sets vertex attributes for next draw. |