Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / include / gpu / GrProcessorStage.h
1
2 /*
3  * Copyright 2010 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8
9
10
11 #ifndef GrProcessorStage_DEFINED
12 #define GrProcessorStage_DEFINED
13
14 #include "GrBackendProcessorFactory.h"
15 #include "GrCoordTransform.h"
16 #include "GrProcessor.h"
17 #include "GrGeometryProcessor.h"
18 #include "GrProgramElementRef.h"
19 #include "SkMatrix.h"
20 #include "SkShader.h"
21
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 {
28 public:
29     explicit GrProcessorStage(const GrProcessor* proc)
30     : fProc(SkRef(proc)) {
31         fCoordChangeMatrixSet = false;
32     }
33
34     GrProcessorStage(const GrProcessorStage& other) {
35         fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
36         if (other.fCoordChangeMatrixSet) {
37             fCoordChangeMatrix = other.fCoordChangeMatrix;
38         }
39         fProc.initAndRef(other.fProc);
40     }
41     
42     static bool AreCompatible(const GrProcessorStage& a, const GrProcessorStage& b,
43                               bool usingExplicitLocalCoords) {
44         SkASSERT(a.fProc.get());
45         SkASSERT(b.fProc.get());
46
47         if (!a.getProcessor()->isEqual(*b.getProcessor())) {
48             return false;
49         }
50
51         // We always track the coord change matrix, but it has no effect when explicit local coords
52         // are used.
53         if (usingExplicitLocalCoords) {
54             return true;
55         }
56
57         if (a.fCoordChangeMatrixSet != b.fCoordChangeMatrixSet) {
58             return false;
59         }
60
61         if (!a.fCoordChangeMatrixSet) {
62             return true;
63         }
64
65         return a.fCoordChangeMatrix == b.fCoordChangeMatrix;
66     }
67
68     /**
69      * This is called when the coordinate system in which the geometry is specified will change.
70      *
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.
73      */
74     void localCoordChange(const SkMatrix& matrix) {
75         if (fCoordChangeMatrixSet) {
76             fCoordChangeMatrix.preConcat(matrix);
77         } else {
78             fCoordChangeMatrixSet = true;
79             fCoordChangeMatrix = matrix;
80         }
81     }
82
83     class SavedCoordChange {
84     public:
85         SkDEBUGCODE(SavedCoordChange() : fEffectUniqueID(SK_InvalidUniqueID) {})
86     private:
87         bool fCoordChangeMatrixSet;
88         SkMatrix fCoordChangeMatrix;
89         SkDEBUGCODE(mutable uint32_t fEffectUniqueID;)
90
91         friend class GrProcessorStage;
92     };
93
94     /**
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).
99      */
100     void saveCoordChange(SavedCoordChange* savedCoordChange) const {
101         savedCoordChange->fCoordChangeMatrixSet = fCoordChangeMatrixSet;
102         if (fCoordChangeMatrixSet) {
103             savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix;
104         }
105         SkASSERT(SK_InvalidUniqueID == savedCoordChange->fEffectUniqueID);
106         SkDEBUGCODE(savedCoordChange->fEffectUniqueID = fProc->getUniqueID();)
107     }
108
109     /**
110      * This balances the saveCoordChange call.
111      */
112     void restoreCoordChange(const SavedCoordChange& savedCoordChange) {
113         fCoordChangeMatrixSet = savedCoordChange.fCoordChangeMatrixSet;
114         if (fCoordChangeMatrixSet) {
115             fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix;
116         }
117         SkASSERT(savedCoordChange.fEffectUniqueID == fProc->getUniqueID());
118         SkDEBUGCODE(savedCoordChange.fEffectUniqueID = SK_InvalidUniqueID);
119     }
120
121     /**
122      * Gets the matrix representing all changes of coordinate system since the GrProcessor was
123      * installed in the stage.
124      */
125     const SkMatrix& getCoordChangeMatrix() const {
126         if (fCoordChangeMatrixSet) {
127             return fCoordChangeMatrix;
128         } else {
129             return SkMatrix::I();
130         }
131     }
132
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();
140         }
141
142         int combinedTypes = type0 | type1;
143         if (SkMatrix::kPerspective_Mask & combinedTypes) {
144           return true;
145         } else {
146           return false;
147         }
148     }
149
150     const GrProcessor* getProcessor() const { return fProc.get(); }
151
152     void convertToPendingExec() { fProc.convertToPendingExec(); }
153
154 private:
155     bool                                   fCoordChangeMatrixSet;
156     SkMatrix                               fCoordChangeMatrix;
157     GrProgramElementRef<const GrProcessor> fProc;
158 };
159
160 class GrFragmentStage : public GrProcessorStage {
161 public:
162     GrFragmentStage(const GrFragmentProcessor* fp) : GrProcessorStage(fp) {}
163
164     const GrFragmentProcessor* getFragmentProcessor() const {
165         return static_cast<const GrFragmentProcessor*>(this->getProcessor());
166     }
167 };
168
169 class GrGeometryStage : public GrProcessorStage {
170 public:
171     GrGeometryStage(const GrGeometryProcessor* gp) : GrProcessorStage(gp) {}
172
173     const GrGeometryProcessor* getGeometryProcessor() const {
174         return static_cast<const GrGeometryProcessor*>(this->getProcessor());
175     }
176 };
177
178 #endif