| Index: src/gpu/GrDrawState.h
|
| diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
|
| index 5b1194d0c2672da56904c819b50349fb2906b4fb..9d1e64d1fe41efcbd1146f8a8d9ccbcb88bbd8b9 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.
|
|
|