Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / effects / GrConvexPolyEffect.cpp
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 "gl/builders/GrGLProgramBuilder.h"
9 #include "GrConvexPolyEffect.h"
10
11 #include "gl/GrGLProcessor.h"
12 #include "gl/GrGLSL.h"
13 #include "GrTBackendProcessorFactory.h"
14
15 #include "SkPath.h"
16
17 //////////////////////////////////////////////////////////////////////////////
18 class GLAARectEffect;
19
20 class AARectEffect : public GrFragmentProcessor {
21 public:
22     typedef GLAARectEffect GLProcessor;
23
24     const SkRect& getRect() const { return fRect; }
25
26     static const char* Name() { return "AARect"; }
27
28     static GrFragmentProcessor* Create(GrPrimitiveEdgeType edgeType, const SkRect& rect) {
29         return SkNEW_ARGS(AARectEffect, (edgeType, rect));
30     }
31
32     virtual void getConstantColorComponents(GrColor* color,
33                                             uint32_t* validFlags) const SK_OVERRIDE {
34         if (fRect.isEmpty()) {
35             // An empty rect will have no coverage anywhere.
36             *color = 0x00000000;
37             *validFlags = kRGBA_GrColorComponentFlags;
38         } else {
39             *validFlags = 0;
40         }
41     }
42
43     GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
44
45     virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE;
46
47 private:
48     AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect) : fRect(rect), fEdgeType(edgeType) {
49         this->setWillReadFragmentPosition();
50     }
51
52     virtual bool onIsEqual(const GrProcessor& other) const SK_OVERRIDE {
53         const AARectEffect& aare = other.cast<AARectEffect>();
54         return fRect == aare.fRect;
55     }
56
57     SkRect              fRect;
58     GrPrimitiveEdgeType fEdgeType;
59
60     typedef GrFragmentProcessor INHERITED;
61
62     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
63
64 };
65
66 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(AARectEffect);
67
68 GrFragmentProcessor* AARectEffect::TestCreate(SkRandom* random,
69                                               GrContext*,
70                                               const GrDrawTargetCaps& caps,
71                                               GrTexture*[]) {
72     SkRect rect = SkRect::MakeLTRB(random->nextSScalar1(),
73                                    random->nextSScalar1(),
74                                    random->nextSScalar1(),
75                                    random->nextSScalar1());
76     GrFragmentProcessor* fp;
77     do {
78         GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(random->nextULessThan(
79                                                                     kGrProcessorEdgeTypeCnt));
80
81         fp = AARectEffect::Create(edgeType, rect);
82     } while (NULL == fp);
83     return fp;
84 }
85
86 //////////////////////////////////////////////////////////////////////////////
87
88 class GLAARectEffect : public GrGLFragmentProcessor {
89 public:
90     GLAARectEffect(const GrBackendProcessorFactory&, const GrProcessor&);
91
92     virtual void emitCode(GrGLProgramBuilder* builder,
93                           const GrFragmentProcessor& fp,
94                           const GrProcessorKey& key,
95                           const char* outputColor,
96                           const char* inputColor,
97                           const TransformedCoordsArray&,
98                           const TextureSamplerArray&) SK_OVERRIDE;
99
100     static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);
101
102     virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
103
104 private:
105     GrGLProgramDataManager::UniformHandle fRectUniform;
106     SkRect                                fPrevRect;
107     typedef GrGLFragmentProcessor INHERITED;
108 };
109
110 GLAARectEffect::GLAARectEffect(const GrBackendProcessorFactory& factory,
111                                const GrProcessor& effect)
112     : INHERITED (factory) {
113     fPrevRect.fLeft = SK_ScalarNaN;
114 }
115
116 void GLAARectEffect::emitCode(GrGLProgramBuilder* builder,
117                               const GrFragmentProcessor& fp,
118                               const GrProcessorKey& key,
119                               const char* outputColor,
120                               const char* inputColor,
121                               const TransformedCoordsArray&,
122                               const TextureSamplerArray& samplers) {
123     const AARectEffect& aare = fp.cast<AARectEffect>();
124     const char *rectName;
125     // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
126     // respectively.
127     fRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
128                                        kVec4f_GrSLType,
129                                        "rect",
130                                        &rectName);
131
132     GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
133     const char* fragmentPos = fsBuilder->fragmentPosition();
134     if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
135         // The amount of coverage removed in x and y by the edges is computed as a pair of negative
136         // numbers, xSub and ySub.
137         fsBuilder->codeAppend("\t\tfloat xSub, ySub;\n");
138         fsBuilder->codeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName);
139         fsBuilder->codeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos);
140         fsBuilder->codeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName);
141         fsBuilder->codeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos);
142         // Now compute coverage in x and y and multiply them to get the fraction of the pixel
143         // covered.
144         fsBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
145     } else {
146         fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
147         fsBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
148         fsBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
149         fsBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
150         fsBuilder->codeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
151     }
152
153     if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) {
154         fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
155     }
156     fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
157                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
158 }
159
160 void GLAARectEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) {
161     const AARectEffect& aare = processor.cast<AARectEffect>();
162     const SkRect& rect = aare.getRect();
163     if (rect != fPrevRect) {
164         pdman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
165                    rect.fRight - 0.5f, rect.fBottom - 0.5f);
166         fPrevRect = rect;
167     }
168 }
169
170 void GLAARectEffect::GenKey(const GrProcessor& processor, const GrGLCaps&,
171                             GrProcessorKeyBuilder* b) {
172     const AARectEffect& aare = processor.cast<AARectEffect>();
173     b->add32(aare.getEdgeType());
174 }
175
176 const GrBackendFragmentProcessorFactory& AARectEffect::getFactory() const {
177     return GrTBackendFragmentProcessorFactory<AARectEffect>::getInstance();
178 }
179
180 //////////////////////////////////////////////////////////////////////////////
181
182 class GrGLConvexPolyEffect : public GrGLFragmentProcessor {
183 public:
184     GrGLConvexPolyEffect(const GrBackendProcessorFactory&, const GrProcessor&);
185
186     virtual void emitCode(GrGLProgramBuilder* builder,
187                           const GrFragmentProcessor& fp,
188                           const GrProcessorKey& key,
189                           const char* outputColor,
190                           const char* inputColor,
191                           const TransformedCoordsArray&,
192                           const TextureSamplerArray&) SK_OVERRIDE;
193
194     static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);
195
196     virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
197
198 private:
199     GrGLProgramDataManager::UniformHandle fEdgeUniform;
200     SkScalar                              fPrevEdges[3 * GrConvexPolyEffect::kMaxEdges];
201     typedef GrGLFragmentProcessor INHERITED;
202 };
203
204 GrGLConvexPolyEffect::GrGLConvexPolyEffect(const GrBackendProcessorFactory& factory,
205                                            const GrProcessor&)
206     : INHERITED (factory) {
207     fPrevEdges[0] = SK_ScalarNaN;
208 }
209
210 void GrGLConvexPolyEffect::emitCode(GrGLProgramBuilder* builder,
211                                     const GrFragmentProcessor& fp,
212                                     const GrProcessorKey& key,
213                                     const char* outputColor,
214                                     const char* inputColor,
215                                     const TransformedCoordsArray&,
216                                     const TextureSamplerArray& samplers) {
217     const GrConvexPolyEffect& cpe = fp.cast<GrConvexPolyEffect>();
218
219     const char *edgeArrayName;
220     fEdgeUniform = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
221                                             kVec3f_GrSLType,
222                                             "edges",
223                                             cpe.getEdgeCount(),
224                                             &edgeArrayName);
225     GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
226     fsBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
227     fsBuilder->codeAppend("\t\tfloat edge;\n");
228     const char* fragmentPos = fsBuilder->fragmentPosition();
229     for (int i = 0; i < cpe.getEdgeCount(); ++i) {
230         fsBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n",
231                                edgeArrayName, i, fragmentPos, fragmentPos);
232         if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
233             fsBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
234         } else {
235             fsBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
236         }
237         fsBuilder->codeAppend("\t\talpha *= edge;\n");
238     }
239
240     // Woe is me. See skbug.com/2149.
241     if (kTegra2_GrGLRenderer == builder->ctxInfo().renderer()) {
242         fsBuilder->codeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n");
243     }
244
245     if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
246         fsBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
247     }
248     fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
249                            (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
250 }
251
252 void GrGLConvexPolyEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& effect) {
253     const GrConvexPolyEffect& cpe = effect.cast<GrConvexPolyEffect>();
254     size_t byteSize = 3 * cpe.getEdgeCount() * sizeof(SkScalar);
255     if (0 != memcmp(fPrevEdges, cpe.getEdges(), byteSize)) {
256         pdman.set3fv(fEdgeUniform, cpe.getEdgeCount(), cpe.getEdges());
257         memcpy(fPrevEdges, cpe.getEdges(), byteSize);
258     }
259 }
260
261 void GrGLConvexPolyEffect::GenKey(const GrProcessor& processor, const GrGLCaps&,
262                                   GrProcessorKeyBuilder* b) {
263     const GrConvexPolyEffect& cpe = processor.cast<GrConvexPolyEffect>();
264     GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8);
265     uint32_t key = (cpe.getEdgeCount() << 3) | cpe.getEdgeType();
266     b->add32(key);
267 }
268
269 //////////////////////////////////////////////////////////////////////////////
270
271 GrFragmentProcessor* GrConvexPolyEffect::Create(GrPrimitiveEdgeType type, const SkPath& path,
272                                                 const SkVector* offset) {
273     if (kHairlineAA_GrProcessorEdgeType == type) {
274         return NULL;
275     }
276     if (path.getSegmentMasks() != SkPath::kLine_SegmentMask ||
277         !path.isConvex()) {
278         return NULL;
279     }
280
281     if (path.countPoints() > kMaxEdges) {
282         return NULL;
283     }
284
285     SkPoint pts[kMaxEdges];
286     SkScalar edges[3 * kMaxEdges];
287
288     SkPath::Direction dir;
289     SkAssertResult(path.cheapComputeDirection(&dir));
290
291     SkVector t;
292     if (NULL == offset) {
293         t.set(0, 0);
294     } else {
295         t = *offset;
296     }
297
298     int count = path.getPoints(pts, kMaxEdges);
299     int n = 0;
300     for (int lastPt = count - 1, i = 0; i < count; lastPt = i++) {
301         if (pts[lastPt] != pts[i]) {
302             SkVector v = pts[i] - pts[lastPt];
303             v.normalize();
304             if (SkPath::kCCW_Direction == dir) {
305                 edges[3 * n] = v.fY;
306                 edges[3 * n + 1] = -v.fX;
307             } else {
308                 edges[3 * n] = -v.fY;
309                 edges[3 * n + 1] = v.fX;
310             }
311             SkPoint p = pts[i] + t;
312             edges[3 * n + 2] = -(edges[3 * n] * p.fX + edges[3 * n + 1] * p.fY);
313             ++n;
314         }
315     }
316     if (path.isInverseFillType()) {
317         type = GrInvertProcessorEdgeType(type);
318     }
319     return Create(type, n, edges);
320 }
321
322 GrFragmentProcessor* GrConvexPolyEffect::Create(GrPrimitiveEdgeType edgeType, const SkRect& rect) {
323     if (kHairlineAA_GrProcessorEdgeType == edgeType){
324         return NULL;
325     }
326     return AARectEffect::Create(edgeType, rect);
327 }
328
329 GrConvexPolyEffect::~GrConvexPolyEffect() {}
330
331 void GrConvexPolyEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
332     *validFlags = 0;
333 }
334
335 const GrBackendFragmentProcessorFactory& GrConvexPolyEffect::getFactory() const {
336     return GrTBackendFragmentProcessorFactory<GrConvexPolyEffect>::getInstance();
337 }
338
339 GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[])
340     : fEdgeType(edgeType)
341     , fEdgeCount(n) {
342     // Factory function should have already ensured this.
343     SkASSERT(n <= kMaxEdges);
344     memcpy(fEdges, edges, 3 * n * sizeof(SkScalar));
345     // Outset the edges by 0.5 so that a pixel with center on an edge is 50% covered in the AA case
346     // and 100% covered in the non-AA case.
347     for (int i = 0; i < n; ++i) {
348         fEdges[3 * i + 2] += SK_ScalarHalf;
349     }
350     this->setWillReadFragmentPosition();
351 }
352
353 bool GrConvexPolyEffect::onIsEqual(const GrProcessor& other) const {
354     const GrConvexPolyEffect& cpe = other.cast<GrConvexPolyEffect>();
355     // ignore the fact that 0 == -0 and just use memcmp.
356     return (cpe.fEdgeType == fEdgeType && cpe.fEdgeCount == fEdgeCount &&
357             0 == memcmp(cpe.fEdges, fEdges, 3 * fEdgeCount * sizeof(SkScalar)));
358 }
359
360 //////////////////////////////////////////////////////////////////////////////
361
362 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConvexPolyEffect);
363
364 GrFragmentProcessor* GrConvexPolyEffect::TestCreate(SkRandom* random,
365                                                     GrContext*,
366                                                     const GrDrawTargetCaps& caps,
367                                                     GrTexture*[]) {
368     int count = random->nextULessThan(kMaxEdges) + 1;
369     SkScalar edges[kMaxEdges * 3];
370     for (int i = 0; i < 3 * count; ++i) {
371         edges[i] = random->nextSScalar1();
372     }
373
374     GrFragmentProcessor* fp;
375     do {
376         GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
377                                         random->nextULessThan(kGrProcessorEdgeTypeCnt));
378         fp = GrConvexPolyEffect::Create(edgeType, count, edges);
379     } while (NULL == fp);
380     return fp;
381 }