aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrDrawState.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/GrDrawState.h')
-rw-r--r--src/gpu/GrDrawState.h305
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.