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 "GrConvexPolyEffect.h"
9 #include "GrInvariantOutput.h"
10 #include "SkPathPriv.h"
11 #include "glsl/GrGLSLFragmentProcessor.h"
12 #include "glsl/GrGLSLFragmentShaderBuilder.h"
13 #include "glsl/GrGLSLProgramDataManager.h"
14 #include "glsl/GrGLSLUniformHandler.h"
15
16 //////////////////////////////////////////////////////////////////////////////
17 class AARectEffect : public GrFragmentProcessor {
18 public:
getRect() const19 const SkRect& getRect() const { return fRect; }
20
Create(GrPrimitiveEdgeType edgeType,const SkRect & rect)21 static GrFragmentProcessor* Create(GrPrimitiveEdgeType edgeType, const SkRect& rect) {
22 return new AARectEffect(edgeType, rect);
23 }
24
getEdgeType() const25 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
26
name() const27 const char* name() const override { return "AARect"; }
28
29 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
30
31 private:
AARectEffect(GrPrimitiveEdgeType edgeType,const SkRect & rect)32 AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect)
33 : fRect(rect), fEdgeType(edgeType) {
34 this->initClassID<AARectEffect>();
35 this->setWillReadFragmentPosition();
36 }
37
38 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
39
onIsEqual(const GrFragmentProcessor & other) const40 bool onIsEqual(const GrFragmentProcessor& other) const override {
41 const AARectEffect& aare = other.cast<AARectEffect>();
42 return fRect == aare.fRect;
43 }
44
onComputeInvariantOutput(GrInvariantOutput * inout) const45 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
46 if (fRect.isEmpty()) {
47 // An empty rect will have no coverage anywhere.
48 inout->mulByKnownSingleComponent(0);
49 } else {
50 inout->mulByUnknownSingleComponent();
51 }
52 }
53
54 SkRect fRect;
55 GrPrimitiveEdgeType fEdgeType;
56
57 typedef GrFragmentProcessor INHERITED;
58
59 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
60
61 };
62
63 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(AARectEffect);
64
TestCreate(GrProcessorTestData * d)65 const GrFragmentProcessor* AARectEffect::TestCreate(GrProcessorTestData* d) {
66 SkRect rect = SkRect::MakeLTRB(d->fRandom->nextSScalar1(),
67 d->fRandom->nextSScalar1(),
68 d->fRandom->nextSScalar1(),
69 d->fRandom->nextSScalar1());
70 GrFragmentProcessor* fp;
71 do {
72 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
73 d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
74
75 fp = AARectEffect::Create(edgeType, rect);
76 } while (nullptr == fp);
77 return fp;
78 }
79
80 //////////////////////////////////////////////////////////////////////////////
81
82 class GLAARectEffect : public GrGLSLFragmentProcessor {
83 public:
GLAARectEffect()84 GLAARectEffect() {
85 fPrevRect.fLeft = SK_ScalarNaN;
86 }
87
88 void emitCode(EmitArgs&) override;
89
90 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
91
92 protected:
93 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
94
95 private:
96 GrGLSLProgramDataManager::UniformHandle fRectUniform;
97 SkRect fPrevRect;
98
99 typedef GrGLSLFragmentProcessor INHERITED;
100 };
101
emitCode(EmitArgs & args)102 void GLAARectEffect::emitCode(EmitArgs& args) {
103 const AARectEffect& aare = args.fFp.cast<AARectEffect>();
104 const char *rectName;
105 // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
106 // respectively.
107 fRectUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
108 kVec4f_GrSLType,
109 kDefault_GrSLPrecision,
110 "rect",
111 &rectName);
112
113 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
114 const char* fragmentPos = fragBuilder->fragmentPosition();
115 if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
116 // The amount of coverage removed in x and y by the edges is computed as a pair of negative
117 // numbers, xSub and ySub.
118 fragBuilder->codeAppend("\t\tfloat xSub, ySub;\n");
119 fragBuilder->codeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName);
120 fragBuilder->codeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos);
121 fragBuilder->codeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName);
122 fragBuilder->codeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos);
123 // Now compute coverage in x and y and multiply them to get the fraction of the pixel
124 // covered.
125 fragBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
126 } else {
127 fragBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
128 fragBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
129 fragBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
130 fragBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
131 fragBuilder->codeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
132 }
133
134 if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) {
135 fragBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
136 }
137 fragBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
138 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
139 }
140
onSetData(const GrGLSLProgramDataManager & pdman,const GrProcessor & processor)141 void GLAARectEffect::onSetData(const GrGLSLProgramDataManager& pdman,
142 const GrProcessor& processor) {
143 const AARectEffect& aare = processor.cast<AARectEffect>();
144 const SkRect& rect = aare.getRect();
145 if (rect != fPrevRect) {
146 pdman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
147 rect.fRight - 0.5f, rect.fBottom - 0.5f);
148 fPrevRect = rect;
149 }
150 }
151
GenKey(const GrProcessor & processor,const GrGLSLCaps &,GrProcessorKeyBuilder * b)152 void GLAARectEffect::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
153 GrProcessorKeyBuilder* b) {
154 const AARectEffect& aare = processor.cast<AARectEffect>();
155 b->add32(aare.getEdgeType());
156 }
157
onGetGLSLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const158 void AARectEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const {
159 GLAARectEffect::GenKey(*this, caps, b);
160 }
161
onCreateGLSLInstance() const162 GrGLSLFragmentProcessor* AARectEffect::onCreateGLSLInstance() const {
163 return new GLAARectEffect;
164 }
165
166 //////////////////////////////////////////////////////////////////////////////
167
168 class GrGLConvexPolyEffect : public GrGLSLFragmentProcessor {
169 public:
GrGLConvexPolyEffect()170 GrGLConvexPolyEffect() {
171 fPrevEdges[0] = SK_ScalarNaN;
172 }
173
174 void emitCode(EmitArgs&) override;
175
176 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
177
178 protected:
179 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
180
181 private:
182 GrGLSLProgramDataManager::UniformHandle fEdgeUniform;
183 SkScalar fPrevEdges[3 * GrConvexPolyEffect::kMaxEdges];
184 typedef GrGLSLFragmentProcessor INHERITED;
185 };
186
emitCode(EmitArgs & args)187 void GrGLConvexPolyEffect::emitCode(EmitArgs& args) {
188 const GrConvexPolyEffect& cpe = args.fFp.cast<GrConvexPolyEffect>();
189
190 const char *edgeArrayName;
191 fEdgeUniform = args.fUniformHandler->addUniformArray(kFragment_GrShaderFlag,
192 kVec3f_GrSLType,
193 kDefault_GrSLPrecision,
194 "edges",
195 cpe.getEdgeCount(),
196 &edgeArrayName);
197 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
198 fragBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
199 fragBuilder->codeAppend("\t\tfloat edge;\n");
200 const char* fragmentPos = fragBuilder->fragmentPosition();
201 for (int i = 0; i < cpe.getEdgeCount(); ++i) {
202 fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n",
203 edgeArrayName, i, fragmentPos, fragmentPos);
204 if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
205 fragBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
206 } else {
207 fragBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
208 }
209 fragBuilder->codeAppend("\t\talpha *= edge;\n");
210 }
211
212 if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
213 fragBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
214 }
215 fragBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor,
216 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
217 }
218
onSetData(const GrGLSLProgramDataManager & pdman,const GrProcessor & effect)219 void GrGLConvexPolyEffect::onSetData(const GrGLSLProgramDataManager& pdman,
220 const GrProcessor& effect) {
221 const GrConvexPolyEffect& cpe = effect.cast<GrConvexPolyEffect>();
222 size_t byteSize = 3 * cpe.getEdgeCount() * sizeof(SkScalar);
223 if (0 != memcmp(fPrevEdges, cpe.getEdges(), byteSize)) {
224 pdman.set3fv(fEdgeUniform, cpe.getEdgeCount(), cpe.getEdges());
225 memcpy(fPrevEdges, cpe.getEdges(), byteSize);
226 }
227 }
228
GenKey(const GrProcessor & processor,const GrGLSLCaps &,GrProcessorKeyBuilder * b)229 void GrGLConvexPolyEffect::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
230 GrProcessorKeyBuilder* b) {
231 const GrConvexPolyEffect& cpe = processor.cast<GrConvexPolyEffect>();
232 GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8);
233 uint32_t key = (cpe.getEdgeCount() << 3) | cpe.getEdgeType();
234 b->add32(key);
235 }
236
237 //////////////////////////////////////////////////////////////////////////////
238
Create(GrPrimitiveEdgeType type,const SkPath & path,const SkVector * offset)239 GrFragmentProcessor* GrConvexPolyEffect::Create(GrPrimitiveEdgeType type, const SkPath& path,
240 const SkVector* offset) {
241 if (kHairlineAA_GrProcessorEdgeType == type) {
242 return nullptr;
243 }
244 if (path.getSegmentMasks() != SkPath::kLine_SegmentMask ||
245 !path.isConvex()) {
246 return nullptr;
247 }
248
249 if (path.countPoints() > kMaxEdges) {
250 return nullptr;
251 }
252
253 SkPoint pts[kMaxEdges];
254 SkScalar edges[3 * kMaxEdges];
255
256 SkPathPriv::FirstDirection dir;
257 SkAssertResult(SkPathPriv::CheapComputeFirstDirection(path, &dir));
258
259 SkVector t;
260 if (nullptr == offset) {
261 t.set(0, 0);
262 } else {
263 t = *offset;
264 }
265
266 int count = path.getPoints(pts, kMaxEdges);
267 int n = 0;
268 for (int lastPt = count - 1, i = 0; i < count; lastPt = i++) {
269 if (pts[lastPt] != pts[i]) {
270 SkVector v = pts[i] - pts[lastPt];
271 v.normalize();
272 if (SkPathPriv::kCCW_FirstDirection == dir) {
273 edges[3 * n] = v.fY;
274 edges[3 * n + 1] = -v.fX;
275 } else {
276 edges[3 * n] = -v.fY;
277 edges[3 * n + 1] = v.fX;
278 }
279 SkPoint p = pts[i] + t;
280 edges[3 * n + 2] = -(edges[3 * n] * p.fX + edges[3 * n + 1] * p.fY);
281 ++n;
282 }
283 }
284 if (path.isInverseFillType()) {
285 type = GrInvertProcessorEdgeType(type);
286 }
287 return Create(type, n, edges);
288 }
289
Create(GrPrimitiveEdgeType edgeType,const SkRect & rect)290 GrFragmentProcessor* GrConvexPolyEffect::Create(GrPrimitiveEdgeType edgeType, const SkRect& rect) {
291 if (kHairlineAA_GrProcessorEdgeType == edgeType){
292 return nullptr;
293 }
294 return AARectEffect::Create(edgeType, rect);
295 }
296
~GrConvexPolyEffect()297 GrConvexPolyEffect::~GrConvexPolyEffect() {}
298
onComputeInvariantOutput(GrInvariantOutput * inout) const299 void GrConvexPolyEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
300 inout->mulByUnknownSingleComponent();
301 }
302
onGetGLSLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const303 void GrConvexPolyEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
304 GrProcessorKeyBuilder* b) const {
305 GrGLConvexPolyEffect::GenKey(*this, caps, b);
306 }
307
onCreateGLSLInstance() const308 GrGLSLFragmentProcessor* GrConvexPolyEffect::onCreateGLSLInstance() const {
309 return new GrGLConvexPolyEffect;
310 }
311
GrConvexPolyEffect(GrPrimitiveEdgeType edgeType,int n,const SkScalar edges[])312 GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[])
313 : fEdgeType(edgeType)
314 , fEdgeCount(n) {
315 this->initClassID<GrConvexPolyEffect>();
316 // Factory function should have already ensured this.
317 SkASSERT(n <= kMaxEdges);
318 memcpy(fEdges, edges, 3 * n * sizeof(SkScalar));
319 // Outset the edges by 0.5 so that a pixel with center on an edge is 50% covered in the AA case
320 // and 100% covered in the non-AA case.
321 for (int i = 0; i < n; ++i) {
322 fEdges[3 * i + 2] += SK_ScalarHalf;
323 }
324 this->setWillReadFragmentPosition();
325 }
326
onIsEqual(const GrFragmentProcessor & other) const327 bool GrConvexPolyEffect::onIsEqual(const GrFragmentProcessor& other) const {
328 const GrConvexPolyEffect& cpe = other.cast<GrConvexPolyEffect>();
329 // ignore the fact that 0 == -0 and just use memcmp.
330 return (cpe.fEdgeType == fEdgeType && cpe.fEdgeCount == fEdgeCount &&
331 0 == memcmp(cpe.fEdges, fEdges, 3 * fEdgeCount * sizeof(SkScalar)));
332 }
333
334 //////////////////////////////////////////////////////////////////////////////
335
336 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConvexPolyEffect);
337
TestCreate(GrProcessorTestData * d)338 const GrFragmentProcessor* GrConvexPolyEffect::TestCreate(GrProcessorTestData* d) {
339 int count = d->fRandom->nextULessThan(kMaxEdges) + 1;
340 SkScalar edges[kMaxEdges * 3];
341 for (int i = 0; i < 3 * count; ++i) {
342 edges[i] = d->fRandom->nextSScalar1();
343 }
344
345 GrFragmentProcessor* fp;
346 do {
347 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
348 d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
349 fp = GrConvexPolyEffect::Create(edgeType, count, edges);
350 } while (nullptr == fp);
351 return fp;
352 }
353