| |
| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| |
| |
| #ifndef GrEffectStage_DEFINED |
| #define GrEffectStage_DEFINED |
| |
| #include "GrBackendEffectFactory.h" |
| #include "GrEffect.h" |
| #include "SkMatrix.h" |
| #include "GrTypes.h" |
| |
| #include "SkShader.h" |
| |
| class GrEffectStage { |
| public: |
| GrEffectStage() |
| : fEffectRef (NULL) { |
| GR_DEBUGCODE(fSavedCoordChangeCnt = 0;) |
| } |
| |
| ~GrEffectStage() { |
| GrSafeUnref(fEffectRef); |
| GrAssert(0 == fSavedCoordChangeCnt); |
| } |
| |
| bool operator ==(const GrEffectStage& other) const { |
| // first handle cases where one or the other has no effect |
| if (NULL == fEffectRef) { |
| return NULL == other.fEffectRef; |
| } else if (NULL == other.fEffectRef) { |
| return false; |
| } |
| |
| if (!(*this->getEffect())->isEqual(*other.getEffect())) { |
| return false; |
| } |
| |
| if (fCoordChangeMatrixSet != other.fCoordChangeMatrixSet) { |
| return false; |
| } |
| |
| if (!fCoordChangeMatrixSet) { |
| return true; |
| } |
| |
| return fCoordChangeMatrix == other.fCoordChangeMatrix; |
| } |
| |
| bool operator!= (const GrEffectStage& s) const { return !(*this == s); } |
| |
| GrEffectStage& operator= (const GrEffectStage& other) { |
| GrSafeAssign(fEffectRef, other.fEffectRef); |
| fCoordChangeMatrixSet = other.fCoordChangeMatrixSet; |
| if (NULL != fEffectRef && fCoordChangeMatrixSet) { |
| fCoordChangeMatrix = other.fCoordChangeMatrix; |
| } |
| return *this; |
| } |
| |
| /** |
| * This is called when the coordinate system in which the geometry is specified will change. |
| * |
| * @param matrix The transformation from the old coord system in which geometry is specified |
| * to the new one from which it will actually be drawn. |
| */ |
| void localCoordChange(const SkMatrix& matrix) { |
| if (fCoordChangeMatrixSet) { |
| fCoordChangeMatrix.preConcat(matrix); |
| } else { |
| fCoordChangeMatrixSet = true; |
| fCoordChangeMatrix = matrix; |
| } |
| } |
| |
| class SavedCoordChange { |
| private: |
| bool fCoordChangeMatrixSet; |
| SkMatrix fCoordChangeMatrix; |
| GR_DEBUGCODE(mutable SkAutoTUnref<const GrEffectRef> fEffectRef;) |
| |
| friend class GrEffectStage; |
| }; |
| |
| /** |
| * This gets the current coordinate system change. It is the accumulation of |
| * localCoordChange calls since the effect was installed. It is used when then caller |
| * wants to temporarily change the source geometry coord system, draw something, and then |
| * restore the previous coord system (e.g. temporarily draw in device coords). |
| */ |
| void saveCoordChange(SavedCoordChange* savedCoordChange) const { |
| savedCoordChange->fCoordChangeMatrixSet = fCoordChangeMatrixSet; |
| if (fCoordChangeMatrixSet) { |
| savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix; |
| } |
| GrAssert(NULL == savedCoordChange->fEffectRef.get()); |
| GR_DEBUGCODE(GrSafeRef(fEffectRef);) |
| GR_DEBUGCODE(savedCoordChange->fEffectRef.reset(fEffectRef);) |
| GR_DEBUGCODE(++fSavedCoordChangeCnt); |
| } |
| |
| /** |
| * This balances the saveCoordChange call. |
| */ |
| void restoreCoordChange(const SavedCoordChange& savedCoordChange) { |
| fCoordChangeMatrixSet = savedCoordChange.fCoordChangeMatrixSet; |
| if (fCoordChangeMatrixSet) { |
| fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix; |
| } |
| GrAssert(savedCoordChange.fEffectRef.get() == fEffectRef); |
| GR_DEBUGCODE(--fSavedCoordChangeCnt); |
| GR_DEBUGCODE(savedCoordChange.fEffectRef.reset(NULL);) |
| } |
| |
| /** |
| * Used when storing a deferred GrDrawState. The DeferredStage allows resources owned by its |
| * GrEffect to be recycled through the cache. |
| */ |
| class DeferredStage { |
| public: |
| DeferredStage() : fEffect(NULL) { |
| SkDEBUGCODE(fInitialized = false;) |
| } |
| |
| ~DeferredStage() { |
| if (NULL != fEffect) { |
| fEffect->decDeferredRefCounts(); |
| } |
| } |
| |
| void saveFrom(const GrEffectStage& stage) { |
| GrAssert(!fInitialized); |
| if (NULL != stage.fEffectRef) { |
| stage.fEffectRef->get()->incDeferredRefCounts(); |
| fEffect = stage.fEffectRef->get(); |
| fCoordChangeMatrixSet = stage.fCoordChangeMatrixSet; |
| if (fCoordChangeMatrixSet) { |
| fCoordChangeMatrix = stage.fCoordChangeMatrix; |
| } |
| fVertexAttribIndices[0] = stage.fVertexAttribIndices[0]; |
| fVertexAttribIndices[1] = stage.fVertexAttribIndices[1]; |
| } |
| SkDEBUGCODE(fInitialized = true;) |
| } |
| |
| void restoreTo(GrEffectStage* stage) { |
| GrAssert(fInitialized); |
| const GrEffectRef* oldEffectRef = stage->fEffectRef; |
| if (NULL != fEffect) { |
| stage->fEffectRef = GrEffect::CreateEffectRef(fEffect); |
| stage->fCoordChangeMatrixSet = fCoordChangeMatrixSet; |
| if (fCoordChangeMatrixSet) { |
| stage->fCoordChangeMatrix = fCoordChangeMatrix; |
| } |
| stage->fVertexAttribIndices[0] = fVertexAttribIndices[0]; |
| stage->fVertexAttribIndices[1] = fVertexAttribIndices[1]; |
| } else { |
| stage->fEffectRef = NULL; |
| } |
| SkSafeUnref(oldEffectRef); |
| } |
| |
| bool isEqual(const GrEffectStage& stage) const { |
| if (NULL == stage.fEffectRef) { |
| return NULL == fEffect; |
| } else if (NULL == fEffect) { |
| return false; |
| } |
| |
| if (fVertexAttribIndices[0] != stage.fVertexAttribIndices[0] |
| || fVertexAttribIndices[1] != stage.fVertexAttribIndices[1]) { |
| return false; |
| } |
| |
| if (!(*stage.getEffect())->isEqual(*fEffect)) { |
| return false; |
| } |
| |
| if (fCoordChangeMatrixSet != stage.fCoordChangeMatrixSet) { |
| return false; |
| } |
| |
| if (!fCoordChangeMatrixSet) { |
| return true; |
| } |
| |
| return fCoordChangeMatrix == stage.fCoordChangeMatrix; |
| } |
| |
| private: |
| const GrEffect* fEffect; |
| bool fCoordChangeMatrixSet; |
| SkMatrix fCoordChangeMatrix; |
| int fVertexAttribIndices[2]; |
| SkDEBUGCODE(bool fInitialized;) |
| }; |
| |
| /** |
| * Gets the matrix representing all changes of coordinate system since the GrEffect was |
| * installed in the stage. |
| */ |
| const SkMatrix& getCoordChangeMatrix() const { |
| if (fCoordChangeMatrixSet) { |
| return fCoordChangeMatrix; |
| } else { |
| return SkMatrix::I(); |
| } |
| } |
| |
| void reset() { |
| GrSafeSetNull(fEffectRef); |
| } |
| |
| const GrEffectRef* setEffect(const GrEffectRef* EffectRef) { |
| GrAssert(0 == fSavedCoordChangeCnt); |
| GrSafeAssign(fEffectRef, EffectRef); |
| fCoordChangeMatrixSet = false; |
| |
| fVertexAttribIndices[0] = -1; |
| fVertexAttribIndices[1] = -1; |
| |
| return EffectRef; |
| } |
| |
| const GrEffectRef* setEffect(const GrEffectRef* EffectRef, int attr0, int attr1 = -1) { |
| GrAssert(0 == fSavedCoordChangeCnt); |
| GrSafeAssign(fEffectRef, EffectRef); |
| fCoordChangeMatrixSet = false; |
| |
| fVertexAttribIndices[0] = attr0; |
| fVertexAttribIndices[1] = attr1; |
| |
| return EffectRef; |
| } |
| |
| const GrEffectRef* getEffect() const { return fEffectRef; } |
| |
| const int* getVertexAttribIndices() const { return fVertexAttribIndices; } |
| int getVertexAttribIndexCount() const { return fEffectRef->get()->numVertexAttribs(); } |
| |
| private: |
| bool fCoordChangeMatrixSet; |
| SkMatrix fCoordChangeMatrix; |
| const GrEffectRef* fEffectRef; |
| int fVertexAttribIndices[2]; |
| |
| GR_DEBUGCODE(mutable int fSavedCoordChangeCnt;) |
| }; |
| |
| #endif |