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