OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef GrProcessor_DEFINED | 8 #ifndef GrProcessor_DEFINED |
9 #define GrProcessor_DEFINED | 9 #define GrProcessor_DEFINED |
10 | 10 |
11 #include "GrBackendProcessorFactory.h" | 11 #include "GrBackendProcessorFactory.h" |
12 #include "GrColor.h" | 12 #include "GrColor.h" |
13 #include "GrProcessorUnitTest.h" | 13 #include "GrProcessorUnitTest.h" |
14 #include "GrProgramElement.h" | 14 #include "GrProgramElement.h" |
15 #include "GrTextureAccess.h" | 15 #include "GrTextureAccess.h" |
16 #include "SkMath.h" | 16 #include "SkMath.h" |
17 | 17 |
18 class GrContext; | 18 class GrContext; |
19 class GrCoordTransform; | 19 class GrCoordTransform; |
| 20 class GrInvariantOutput; |
20 | 21 |
21 /** Provides custom shader code to the Ganesh shading pipeline. GrProcessor obje
cts *must* be | 22 /** Provides custom shader code to the Ganesh shading pipeline. GrProcessor obje
cts *must* be |
22 immutable: after being constructed, their fields may not change. | 23 immutable: after being constructed, their fields may not change. |
23 | 24 |
24 Dynamically allocated GrProcessors are managed by a per-thread memory pool.
The ref count of an | 25 Dynamically allocated GrProcessors are managed by a per-thread memory pool.
The ref count of an |
25 processor must reach 0 before the thread terminates and the pool is destroye
d. To create a | 26 processor must reach 0 before the thread terminates and the pool is destroye
d. To create a |
26 static processor use the helper macro GR_CREATE_STATIC_PROCESSOR declared be
low. | 27 static processor use the helper macro GR_CREATE_STATIC_PROCESSOR declared be
low. |
27 */ | 28 */ |
28 class GrProcessor : public GrProgramElement { | 29 class GrProcessor : public GrProgramElement { |
29 public: | 30 public: |
30 SK_DECLARE_INST_COUNT(GrProcessor) | 31 SK_DECLARE_INST_COUNT(GrProcessor) |
31 | 32 |
32 virtual ~GrProcessor(); | 33 virtual ~GrProcessor(); |
33 | 34 |
34 struct InvariantOutput{ | |
35 InvariantOutput() : fColor(0), fValidFlags(0), fIsSingleComponent(false)
, | |
36 fNonMulStageFound(false), fWillUseInputColor(true) {
} | |
37 | |
38 enum ReadInput { | |
39 kWill_ReadInput, | |
40 kWillNot_ReadInput, | |
41 }; | |
42 | |
43 void mulByUnknownOpaqueColor() { | |
44 if (this->isOpaque()) { | |
45 fValidFlags = kA_GrColorComponentFlag; | |
46 fIsSingleComponent = false; | |
47 } else { | |
48 // Since the current state is not opaque we no longer care if th
e color being | |
49 // multiplied is opaque. | |
50 this->mulByUnknownColor(); | |
51 } | |
52 } | |
53 | |
54 void mulByUnknownColor() { | |
55 if (this->hasZeroAlpha()) { | |
56 this->internalSetToTransparentBlack(); | |
57 } else { | |
58 this->internalSetToUnknown(); | |
59 } | |
60 } | |
61 | |
62 void mulByUnknownAlpha() { | |
63 if (this->hasZeroAlpha()) { | |
64 this->internalSetToTransparentBlack(); | |
65 } else { | |
66 // We don't need to change fIsSingleComponent in this case | |
67 fValidFlags = 0; | |
68 } | |
69 } | |
70 | |
71 void mulByKnownAlpha(uint8_t alpha) { | |
72 if (this->hasZeroAlpha() || 0 == alpha) { | |
73 this->internalSetToTransparentBlack(); | |
74 } else { | |
75 if (alpha != 255) { | |
76 // Multiply color by alpha | |
77 fColor = GrColorPackRGBA(SkMulDiv255Round(GrColorUnpackR(fCo
lor), alpha), | |
78 SkMulDiv255Round(GrColorUnpackG(fCo
lor), alpha), | |
79 SkMulDiv255Round(GrColorUnpackB(fCo
lor), alpha), | |
80 SkMulDiv255Round(GrColorUnpackA(fCo
lor), alpha)); | |
81 } | |
82 } | |
83 } | |
84 | |
85 void invalidateComponents(uint8_t invalidateFlags, ReadInput readsInput)
{ | |
86 fValidFlags &= ~invalidateFlags; | |
87 fIsSingleComponent = false; | |
88 if (kWillNot_ReadInput == readsInput) { | |
89 fWillUseInputColor = false; | |
90 } | |
91 } | |
92 | |
93 void setToOther(uint8_t validFlags, GrColor color, ReadInput readsInput)
{ | |
94 fValidFlags = validFlags; | |
95 fColor = color; | |
96 fIsSingleComponent = false; | |
97 fNonMulStageFound = true; | |
98 if (kWillNot_ReadInput == readsInput) { | |
99 fWillUseInputColor = false; | |
100 } | |
101 } | |
102 | |
103 void setToUnknown(ReadInput readsInput) { | |
104 this->internalSetToUnknown(); | |
105 fNonMulStageFound= true; | |
106 if (kWillNot_ReadInput == readsInput) { | |
107 fWillUseInputColor = false; | |
108 } | |
109 } | |
110 | |
111 bool isOpaque() const { | |
112 return ((fValidFlags & kA_GrColorComponentFlag) && 0xFF == GrColorUn
packA(fColor)); | |
113 } | |
114 | |
115 bool isSolidWhite() const { | |
116 return (fValidFlags == kRGBA_GrColorComponentFlags && 0xFFFFFFFF ==
fColor); | |
117 } | |
118 | |
119 GrColor color() const { return fColor; } | |
120 uint8_t validFlags() const { return fValidFlags; } | |
121 | |
122 /** | |
123 * If isSingleComponent is true, then the flag values for r, g, b, and a
must all be the | |
124 * same. If the flags are all set then all color components must be equa
l. | |
125 */ | |
126 SkDEBUGCODE(void validate() const;) | |
127 | |
128 private: | |
129 void internalSetToTransparentBlack() { | |
130 fValidFlags = kRGBA_GrColorComponentFlags; | |
131 fColor = 0; | |
132 fIsSingleComponent = true; | |
133 } | |
134 | |
135 void internalSetToUnknown() { | |
136 fValidFlags = 0; | |
137 fIsSingleComponent = false; | |
138 } | |
139 | |
140 bool hasZeroAlpha() const { | |
141 return ((fValidFlags & kA_GrColorComponentFlag) && 0 == GrColorUnpac
kA(fColor)); | |
142 } | |
143 | |
144 SkDEBUGCODE(bool colorComponentsAllEqual() const;) | |
145 /** | |
146 * If alpha is valid, check that any valid R,G,B values are <= A | |
147 */ | |
148 SkDEBUGCODE(bool validPreMulColor() const;) | |
149 | |
150 // Friended class that have "controller" code which loop over stages cal
ling | |
151 // computeInvarianteOutput(). These controllers may need to manually adj
ust the internal | |
152 // members of InvariantOutput | |
153 friend class GrDrawState; | |
154 friend class GrOptDrawState; | |
155 friend class GrPaint; | |
156 friend class GrProcessor; | |
157 | |
158 GrColor fColor; | |
159 uint32_t fValidFlags; | |
160 bool fIsSingleComponent; | |
161 bool fNonMulStageFound; | |
162 bool fWillUseInputColor; | |
163 }; | |
164 | |
165 /** | 35 /** |
166 * This function is used to perform optimizations. When called the invarient
Ouput param | 36 * This function is used to perform optimizations. When called the invarient
Ouput param |
167 * indicate whether the input components to this processor in the FS will ha
ve known values. | 37 * indicate whether the input components to this processor in the FS will ha
ve known values. |
168 * In inout the validFlags member is a bitfield of GrColorComponentFlags. Th
e isSingleComponent | 38 * In inout the validFlags member is a bitfield of GrColorComponentFlags. Th
e isSingleComponent |
169 * member indicates whether the input will be 1 or 4 bytes. The function upd
ates the members of | 39 * member indicates whether the input will be 1 or 4 bytes. The function upd
ates the members of |
170 * inout to indicate known values of its output. A component of the color me
mber only has | 40 * inout to indicate known values of its output. A component of the color me
mber only has |
171 * meaning if the corresponding bit in validFlags is set. | 41 * meaning if the corresponding bit in validFlags is set. |
172 */ | 42 */ |
173 void computeInvariantOutput(InvariantOutput* inout) const { | 43 void computeInvariantOutput(GrInvariantOutput* inout) const; |
174 inout->fWillUseInputColor = true; | |
175 this->onComputeInvariantOutput(inout); | |
176 #ifdef SK_DEBUG | |
177 inout->validate(); | |
178 #endif | |
179 } | |
180 | 44 |
181 /** This object, besides creating back-end-specific helper objects, is used
for run-time-type- | 45 /** This object, besides creating back-end-specific helper objects, is used
for run-time-type- |
182 identification. The factory should be an instance of templated class, | 46 identification. The factory should be an instance of templated class, |
183 GrTBackendProcessorFactory. It is templated on the subclass of GrProcess
or. The subclass | 47 GrTBackendProcessorFactory. It is templated on the subclass of GrProcess
or. The subclass |
184 must have a nested type (or typedef) named GLProcessor which will be the
subclass of | 48 must have a nested type (or typedef) named GLProcessor which will be the
subclass of |
185 GrGLProcessor created by the factory. | 49 GrGLProcessor created by the factory. |
186 | 50 |
187 Example: | 51 Example: |
188 class MyCustomProcessor : public GrProcessor { | 52 class MyCustomProcessor : public GrProcessor { |
189 ... | 53 ... |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 bool hasSameTextureAccesses(const GrProcessor&) const; | 104 bool hasSameTextureAccesses(const GrProcessor&) const; |
241 | 105 |
242 /** | 106 /** |
243 * If the prcoessor will generate a backend-specific processor that will rea
d the fragment | 107 * If the prcoessor will generate a backend-specific processor that will rea
d the fragment |
244 * position in the FS then it must call this method from its constructor. Ot
herwise, the | 108 * position in the FS then it must call this method from its constructor. Ot
herwise, the |
245 * request to access the fragment position will be denied. | 109 * request to access the fragment position will be denied. |
246 */ | 110 */ |
247 void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; } | 111 void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; } |
248 | 112 |
249 private: | 113 private: |
250 | |
251 /** | 114 /** |
252 * Subclass implements this to support getConstantColorComponents(...). | 115 * Subclass implements this to support getConstantColorComponents(...). |
253 */ | 116 */ |
254 virtual void onComputeInvariantOutput(InvariantOutput* inout) const = 0; | 117 virtual void onComputeInvariantOutput(GrInvariantOutput* inout) const = 0; |
255 | 118 |
256 SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses; | 119 SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses; |
257 bool fWillReadFragmentPosition; | 120 bool fWillReadFragmentPosition; |
258 | 121 |
259 typedef GrProgramElement INHERITED; | 122 typedef GrProgramElement INHERITED; |
260 }; | 123 }; |
261 | 124 |
262 | 125 |
263 /** | 126 /** |
264 * This creates a processor outside of the memory pool. The processor's destruct
or will be called | 127 * This creates a processor outside of the memory pool. The processor's destruct
or will be called |
265 * at global destruction time. NAME will be the name of the created instance. | 128 * at global destruction time. NAME will be the name of the created instance. |
266 */ | 129 */ |
267 #define GR_CREATE_STATIC_PROCESSOR(NAME, PROC_CLASS, ARGS)
\ | 130 #define GR_CREATE_STATIC_PROCESSOR(NAME, PROC_CLASS, ARGS)
\ |
268 static SkAlignedSStorage<sizeof(PROC_CLASS)> g_##NAME##_Storage;
\ | 131 static SkAlignedSStorage<sizeof(PROC_CLASS)> g_##NAME##_Storage;
\ |
269 static PROC_CLASS* NAME SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), PROC_CLAS
S, ARGS); \ | 132 static PROC_CLASS* NAME SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), PROC_CLAS
S, ARGS); \ |
270 static SkAutoTDestroy<GrProcessor> NAME##_ad(NAME); | 133 static SkAutoTDestroy<GrProcessor> NAME##_ad(NAME); |
271 | 134 |
272 #endif | 135 #endif |
OLD | NEW |