Chromium Code Reviews| Index: src/gpu/GrDrawState.h |
| diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h |
| index 5b1194d0c2672da56904c819b50349fb2906b4fb..c87f36c4ef3d88ce6e79788255392132228be4dc 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 |
|
robertphillips
2013/06/13 15:49:04
hosts -> host
output color -> output color or cove
bsalomon
2013/06/13 19:36:12
Done.
|
| + /// Each stage can hosts a GrEffect. The effect produces an output color 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. |