3 * Copyright 2010 Google Inc.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
11 #ifndef GrProcessorStage_DEFINED
12 #define GrProcessorStage_DEFINED
14 #include "GrBackendProcessorFactory.h"
15 #include "GrCoordTransform.h"
16 #include "GrProcessor.h"
17 #include "GrGeometryProcessor.h"
18 #include "GrProgramElementRef.h"
22 // TODO: Make two variations on this class: One for GrDrawState that only owns regular refs
23 // and supports compatibility checks and changing local coords. The second is for GrOptDrawState,
24 // is immutable, and only owns pending execution refs. This requries removing the common base
25 // class from GrDrawState and GrOptDrawState called GrRODrawState and converting to GrOptDrawState
26 // when draws are enqueued in the GrInOrderDrawBuffer.
27 class GrProcessorStage {
29 explicit GrProcessorStage(const GrProcessor* proc)
30 : fProc(SkRef(proc)) {
31 fCoordChangeMatrixSet = false;
34 GrProcessorStage(const GrProcessorStage& other) {
35 fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
36 if (other.fCoordChangeMatrixSet) {
37 fCoordChangeMatrix = other.fCoordChangeMatrix;
39 fProc.initAndRef(other.fProc);
42 static bool AreCompatible(const GrProcessorStage& a, const GrProcessorStage& b,
43 bool usingExplicitLocalCoords) {
44 SkASSERT(a.fProc.get());
45 SkASSERT(b.fProc.get());
47 if (!a.getProcessor()->isEqual(*b.getProcessor())) {
51 // We always track the coord change matrix, but it has no effect when explicit local coords
53 if (usingExplicitLocalCoords) {
57 if (a.fCoordChangeMatrixSet != b.fCoordChangeMatrixSet) {
61 if (!a.fCoordChangeMatrixSet) {
65 return a.fCoordChangeMatrix == b.fCoordChangeMatrix;
69 * This is called when the coordinate system in which the geometry is specified will change.
71 * @param matrix The transformation from the old coord system in which geometry is specified
72 * to the new one from which it will actually be drawn.
74 void localCoordChange(const SkMatrix& matrix) {
75 if (fCoordChangeMatrixSet) {
76 fCoordChangeMatrix.preConcat(matrix);
78 fCoordChangeMatrixSet = true;
79 fCoordChangeMatrix = matrix;
83 class SavedCoordChange {
85 SkDEBUGCODE(SavedCoordChange() : fEffectUniqueID(SK_InvalidUniqueID) {})
87 bool fCoordChangeMatrixSet;
88 SkMatrix fCoordChangeMatrix;
89 SkDEBUGCODE(mutable uint32_t fEffectUniqueID;)
91 friend class GrProcessorStage;
95 * This gets the current coordinate system change. It is the accumulation of
96 * localCoordChange calls since the effect was installed. It is used when then caller
97 * wants to temporarily change the source geometry coord system, draw something, and then
98 * restore the previous coord system (e.g. temporarily draw in device coords).
100 void saveCoordChange(SavedCoordChange* savedCoordChange) const {
101 savedCoordChange->fCoordChangeMatrixSet = fCoordChangeMatrixSet;
102 if (fCoordChangeMatrixSet) {
103 savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix;
105 SkASSERT(SK_InvalidUniqueID == savedCoordChange->fEffectUniqueID);
106 SkDEBUGCODE(savedCoordChange->fEffectUniqueID = fProc->getUniqueID();)
110 * This balances the saveCoordChange call.
112 void restoreCoordChange(const SavedCoordChange& savedCoordChange) {
113 fCoordChangeMatrixSet = savedCoordChange.fCoordChangeMatrixSet;
114 if (fCoordChangeMatrixSet) {
115 fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix;
117 SkASSERT(savedCoordChange.fEffectUniqueID == fProc->getUniqueID());
118 SkDEBUGCODE(savedCoordChange.fEffectUniqueID = SK_InvalidUniqueID);
122 * Gets the matrix representing all changes of coordinate system since the GrProcessor was
123 * installed in the stage.
125 const SkMatrix& getCoordChangeMatrix() const {
126 if (fCoordChangeMatrixSet) {
127 return fCoordChangeMatrix;
129 return SkMatrix::I();
133 bool isPerspectiveCoordTransform(int matrixIndex, bool useExplicitLocalCoords) const {
134 const GrCoordTransform& coordTransform = this->getProcessor()->coordTransform(matrixIndex);
135 SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
136 SkMatrix::TypeMask type1 = SkMatrix::kIdentity_Mask;
137 if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
138 type1 = useExplicitLocalCoords ?
139 SkMatrix::kIdentity_Mask : this->getCoordChangeMatrix().getType();
142 int combinedTypes = type0 | type1;
143 if (SkMatrix::kPerspective_Mask & combinedTypes) {
150 const GrProcessor* getProcessor() const { return fProc.get(); }
152 void convertToPendingExec() { fProc.convertToPendingExec(); }
155 bool fCoordChangeMatrixSet;
156 SkMatrix fCoordChangeMatrix;
157 GrProgramElementRef<const GrProcessor> fProc;
160 class GrFragmentStage : public GrProcessorStage {
162 GrFragmentStage(const GrFragmentProcessor* fp) : GrProcessorStage(fp) {}
164 const GrFragmentProcessor* getFragmentProcessor() const {
165 return static_cast<const GrFragmentProcessor*>(this->getProcessor());
169 class GrGeometryStage : public GrProcessorStage {
171 GrGeometryStage(const GrGeometryProcessor* gp) : GrProcessorStage(gp) {}
173 const GrGeometryProcessor* getGeometryProcessor() const {
174 return static_cast<const GrGeometryProcessor*>(this->getProcessor());