• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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