Line data Source code
1 : /*
2 : * Copyright 2014 Google Inc.
3 : *
4 : * Use of this source code is governed by a BSD-style license that can be
5 : * found in the LICENSE file.
6 : */
7 :
8 : #include "GrDefaultGeoProcFactory.h"
9 :
10 : #include "SkRefCnt.h"
11 : #include "glsl/GrGLSLFragmentShaderBuilder.h"
12 : #include "glsl/GrGLSLGeometryProcessor.h"
13 : #include "glsl/GrGLSLVertexShaderBuilder.h"
14 : #include "glsl/GrGLSLVarying.h"
15 : #include "glsl/GrGLSLUniformHandler.h"
16 : #include "glsl/GrGLSLUtil.h"
17 :
18 : /*
19 : * The default Geometry Processor simply takes position and multiplies it by the uniform view
20 : * matrix. It also leaves coverage untouched. Behind the scenes, we may add per vertex color or
21 : * local coords.
22 : */
23 :
24 : enum GPFlag {
25 : kColorAttribute_GPFlag = 0x1,
26 : kColorAttributeIsSkColor_GPFlag = 0x2,
27 : kLocalCoordAttribute_GPFlag = 0x4,
28 : kCoverageAttribute_GPFlag = 0x8,
29 : };
30 :
31 0 : class DefaultGeoProc : public GrGeometryProcessor {
32 : public:
33 0 : static sk_sp<GrGeometryProcessor> Make(uint32_t gpTypeFlags,
34 : GrColor color,
35 : const SkMatrix& viewMatrix,
36 : const SkMatrix& localMatrix,
37 : bool localCoordsWillBeRead,
38 : uint8_t coverage) {
39 : return sk_sp<GrGeometryProcessor>(new DefaultGeoProc(
40 0 : gpTypeFlags, color, viewMatrix, localMatrix, coverage, localCoordsWillBeRead));
41 : }
42 :
43 0 : const char* name() const override { return "DefaultGeometryProcessor"; }
44 :
45 0 : const Attribute* inPosition() const { return fInPosition; }
46 0 : const Attribute* inColor() const { return fInColor; }
47 0 : const Attribute* inLocalCoords() const { return fInLocalCoords; }
48 0 : const Attribute* inCoverage() const { return fInCoverage; }
49 0 : GrColor color() const { return fColor; }
50 0 : bool hasVertexColor() const { return SkToBool(fInColor); }
51 0 : const SkMatrix& viewMatrix() const { return fViewMatrix; }
52 0 : const SkMatrix& localMatrix() const { return fLocalMatrix; }
53 0 : bool localCoordsWillBeRead() const { return fLocalCoordsWillBeRead; }
54 0 : uint8_t coverage() const { return fCoverage; }
55 0 : bool hasVertexCoverage() const { return SkToBool(fInCoverage); }
56 :
57 0 : class GLSLProcessor : public GrGLSLGeometryProcessor {
58 : public:
59 0 : GLSLProcessor()
60 0 : : fViewMatrix(SkMatrix::InvalidMatrix()), fColor(GrColor_ILLEGAL), fCoverage(0xff) {}
61 :
62 0 : void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
63 0 : const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>();
64 0 : GrGLSLVertexBuilder* vertBuilder = args.fVertBuilder;
65 0 : GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
66 0 : GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
67 0 : GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
68 :
69 : // emit attributes
70 0 : varyingHandler->emitAttributes(gp);
71 :
72 : // Setup pass through color
73 0 : if (gp.hasVertexColor()) {
74 0 : GrGLSLVertToFrag varying(kVec4f_GrSLType);
75 0 : varyingHandler->addVarying("color", &varying);
76 0 : if (gp.fFlags & kColorAttributeIsSkColor_GPFlag) {
77 : // Do a red/blue swap and premul the color.
78 0 : vertBuilder->codeAppendf("%s = vec4(%s.a*%s.bgr, %s.a);", varying.vsOut(),
79 0 : gp.inColor()->fName, gp.inColor()->fName,
80 0 : gp.inColor()->fName);
81 : } else {
82 0 : vertBuilder->codeAppendf("%s = %s;\n", varying.vsOut(), gp.inColor()->fName);
83 : }
84 0 : fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, varying.fsIn());
85 : } else {
86 0 : this->setupUniformColor(fragBuilder, uniformHandler, args.fOutputColor,
87 0 : &fColorUniform);
88 : }
89 :
90 : // Setup position
91 0 : this->setupPosition(vertBuilder,
92 : uniformHandler,
93 : gpArgs,
94 0 : gp.inPosition()->fName,
95 : gp.viewMatrix(),
96 0 : &fViewMatrixUniform);
97 :
98 0 : if (gp.hasExplicitLocalCoords()) {
99 : // emit transforms with explicit local coords
100 0 : this->emitTransforms(vertBuilder,
101 : varyingHandler,
102 : uniformHandler,
103 : gpArgs->fPositionVar,
104 0 : gp.inLocalCoords()->fName,
105 : gp.localMatrix(),
106 0 : args.fFPCoordTransformHandler);
107 : } else {
108 : // emit transforms with position
109 0 : this->emitTransforms(vertBuilder,
110 : varyingHandler,
111 : uniformHandler,
112 : gpArgs->fPositionVar,
113 0 : gp.inPosition()->fName,
114 : gp.localMatrix(),
115 0 : args.fFPCoordTransformHandler);
116 : }
117 :
118 : // Setup coverage as pass through
119 0 : if (gp.hasVertexCoverage()) {
120 0 : fragBuilder->codeAppendf("float alpha = 1.0;");
121 0 : varyingHandler->addPassThroughAttribute(gp.inCoverage(), "alpha");
122 0 : fragBuilder->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage);
123 0 : } else if (gp.coverage() == 0xff) {
124 0 : fragBuilder->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
125 : } else {
126 : const char* fragCoverage;
127 : fCoverageUniform = uniformHandler->addUniform(kFragment_GrShaderFlag,
128 : kFloat_GrSLType,
129 : kDefault_GrSLPrecision,
130 : "Coverage",
131 0 : &fragCoverage);
132 0 : fragBuilder->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, fragCoverage);
133 : }
134 0 : }
135 :
136 0 : static inline void GenKey(const GrGeometryProcessor& gp,
137 : const GrShaderCaps&,
138 : GrProcessorKeyBuilder* b) {
139 0 : const DefaultGeoProc& def = gp.cast<DefaultGeoProc>();
140 0 : uint32_t key = def.fFlags;
141 0 : key |= (def.coverage() == 0xff) ? 0x10 : 0;
142 0 : key |= (def.localCoordsWillBeRead() && def.localMatrix().hasPerspective()) ? 0x20 : 0x0;
143 0 : key |= ComputePosKey(def.viewMatrix()) << 20;
144 0 : b->add32(key);
145 0 : }
146 :
147 0 : void setData(const GrGLSLProgramDataManager& pdman,
148 : const GrPrimitiveProcessor& gp,
149 : FPCoordTransformIter&& transformIter) override {
150 0 : const DefaultGeoProc& dgp = gp.cast<DefaultGeoProc>();
151 :
152 0 : if (!dgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dgp.viewMatrix())) {
153 0 : fViewMatrix = dgp.viewMatrix();
154 : float viewMatrix[3 * 3];
155 0 : GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
156 0 : pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
157 : }
158 :
159 0 : if (dgp.color() != fColor && !dgp.hasVertexColor()) {
160 : float c[4];
161 0 : GrColorToRGBAFloat(dgp.color(), c);
162 0 : pdman.set4fv(fColorUniform, 1, c);
163 0 : fColor = dgp.color();
164 : }
165 :
166 0 : if (dgp.coverage() != fCoverage && !dgp.hasVertexCoverage()) {
167 0 : pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(dgp.coverage()));
168 0 : fCoverage = dgp.coverage();
169 : }
170 0 : this->setTransformDataHelper(dgp.fLocalMatrix, pdman, &transformIter);
171 0 : }
172 :
173 : private:
174 : SkMatrix fViewMatrix;
175 : GrColor fColor;
176 : uint8_t fCoverage;
177 : UniformHandle fViewMatrixUniform;
178 : UniformHandle fColorUniform;
179 : UniformHandle fCoverageUniform;
180 :
181 : typedef GrGLSLGeometryProcessor INHERITED;
182 : };
183 :
184 0 : void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
185 0 : GLSLProcessor::GenKey(*this, caps, b);
186 0 : }
187 :
188 0 : GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
189 0 : return new GLSLProcessor();
190 : }
191 :
192 : private:
193 0 : DefaultGeoProc(uint32_t gpTypeFlags,
194 : GrColor color,
195 : const SkMatrix& viewMatrix,
196 : const SkMatrix& localMatrix,
197 : uint8_t coverage,
198 : bool localCoordsWillBeRead)
199 0 : : fColor(color)
200 : , fViewMatrix(viewMatrix)
201 : , fLocalMatrix(localMatrix)
202 : , fCoverage(coverage)
203 : , fFlags(gpTypeFlags)
204 0 : , fLocalCoordsWillBeRead(localCoordsWillBeRead) {
205 0 : this->initClassID<DefaultGeoProc>();
206 0 : fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
207 0 : kHigh_GrSLPrecision);
208 0 : if (fFlags & kColorAttribute_GPFlag) {
209 0 : fInColor = &this->addVertexAttrib("inColor", kVec4ub_GrVertexAttribType);
210 : }
211 0 : if (fFlags & kLocalCoordAttribute_GPFlag) {
212 0 : fInLocalCoords = &this->addVertexAttrib("inLocalCoord", kVec2f_GrVertexAttribType,
213 0 : kHigh_GrSLPrecision);
214 0 : this->setHasExplicitLocalCoords();
215 : }
216 0 : if (fFlags & kCoverageAttribute_GPFlag) {
217 0 : fInCoverage = &this->addVertexAttrib("inCoverage", kFloat_GrVertexAttribType);
218 : }
219 0 : }
220 :
221 : const Attribute* fInPosition = nullptr;
222 : const Attribute* fInColor = nullptr;
223 : const Attribute* fInLocalCoords = nullptr;
224 : const Attribute* fInCoverage = nullptr;
225 : GrColor fColor;
226 : SkMatrix fViewMatrix;
227 : SkMatrix fLocalMatrix;
228 : uint8_t fCoverage;
229 : uint32_t fFlags;
230 : bool fLocalCoordsWillBeRead;
231 :
232 : GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
233 :
234 : typedef GrGeometryProcessor INHERITED;
235 : };
236 :
237 : GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DefaultGeoProc);
238 :
239 : #if GR_TEST_UTILS
240 0 : sk_sp<GrGeometryProcessor> DefaultGeoProc::TestCreate(GrProcessorTestData* d) {
241 0 : uint32_t flags = 0;
242 0 : if (d->fRandom->nextBool()) {
243 0 : flags |= kColorAttribute_GPFlag;
244 : }
245 0 : if (d->fRandom->nextBool()) {
246 0 : flags |= kColorAttributeIsSkColor_GPFlag;
247 : }
248 0 : if (d->fRandom->nextBool()) {
249 0 : flags |= kCoverageAttribute_GPFlag;
250 : }
251 0 : if (d->fRandom->nextBool()) {
252 0 : flags |= kLocalCoordAttribute_GPFlag;
253 : }
254 :
255 : return DefaultGeoProc::Make(flags,
256 : GrRandomColor(d->fRandom),
257 : GrTest::TestMatrix(d->fRandom),
258 : GrTest::TestMatrix(d->fRandom),
259 :
260 0 : d->fRandom->nextBool(),
261 0 : GrRandomCoverage(d->fRandom));
262 : }
263 : #endif
264 :
265 0 : sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::Make(const Color& color,
266 : const Coverage& coverage,
267 : const LocalCoords& localCoords,
268 : const SkMatrix& viewMatrix) {
269 0 : uint32_t flags = 0;
270 0 : if (Color::kPremulGrColorAttribute_Type == color.fType) {
271 0 : flags |= kColorAttribute_GPFlag;
272 0 : } else if (Color::kUnpremulSkColorAttribute_Type == color.fType) {
273 0 : flags |= kColorAttribute_GPFlag | kColorAttributeIsSkColor_GPFlag;
274 : }
275 0 : flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverageAttribute_GPFlag : 0;
276 0 : flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoordAttribute_GPFlag : 0;
277 :
278 0 : uint8_t inCoverage = coverage.fCoverage;
279 0 : bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type;
280 :
281 0 : GrColor inColor = color.fColor;
282 : return DefaultGeoProc::Make(flags,
283 : inColor,
284 : viewMatrix,
285 0 : localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(),
286 : localCoordsWillBeRead,
287 0 : inCoverage);
288 : }
289 :
290 0 : sk_sp<GrGeometryProcessor> GrDefaultGeoProcFactory::MakeForDeviceSpace(
291 : const Color& color,
292 : const Coverage& coverage,
293 : const LocalCoords& localCoords,
294 : const SkMatrix& viewMatrix) {
295 0 : SkMatrix invert = SkMatrix::I();
296 0 : if (LocalCoords::kUnused_Type != localCoords.fType) {
297 0 : SkASSERT(LocalCoords::kUsePosition_Type == localCoords.fType);
298 0 : if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
299 0 : SkDebugf("Could not invert\n");
300 0 : return nullptr;
301 : }
302 :
303 0 : if (localCoords.hasLocalMatrix()) {
304 0 : invert.preConcat(*localCoords.fMatrix);
305 : }
306 : }
307 :
308 0 : LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert);
309 0 : return Make(color, coverage, inverted, SkMatrix::I());
310 : }
|