blob: a231df495d30794e42513fc5a3f0afec54c92058 [file] [log] [blame]
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +00001/*
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"
egdaniel605dd0f2014-11-12 08:35:25 -08009#include "GrInvariantOutput.h"
joshualitteb2a6762014-12-04 11:35:33 -080010#include "SkPath.h"
joshualittb0a8a372014-09-23 09:50:21 -070011#include "gl/GrGLProcessor.h"
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000012#include "gl/GrGLSL.h"
joshualitteb2a6762014-12-04 11:35:33 -080013#include "gl/builders/GrGLProgramBuilder.h"
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000014
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000015//////////////////////////////////////////////////////////////////////////////
joshualittb0a8a372014-09-23 09:50:21 -070016class AARectEffect : public GrFragmentProcessor {
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000017public:
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000018 const SkRect& getRect() const { return fRect; }
19
joshualittb0a8a372014-09-23 09:50:21 -070020 static GrFragmentProcessor* Create(GrPrimitiveEdgeType edgeType, const SkRect& rect) {
bsalomon55fad7a2014-07-08 07:34:20 -070021 return SkNEW_ARGS(AARectEffect, (edgeType, rect));
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000022 }
23
joshualittb0a8a372014-09-23 09:50:21 -070024 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +000025
mtklein36352bf2015-03-25 18:17:31 -070026 const char* name() const override { return "AARect"; }
joshualitteb2a6762014-12-04 11:35:33 -080027
mtklein36352bf2015-03-25 18:17:31 -070028 void getGLProcessorKey(const GrGLCaps&, GrProcessorKeyBuilder*) const override;
joshualitteb2a6762014-12-04 11:35:33 -080029
mtklein36352bf2015-03-25 18:17:31 -070030 GrGLFragmentProcessor* createGLInstance() const override;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000031
32private:
joshualitteb2a6762014-12-04 11:35:33 -080033 AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect)
34 : fRect(rect), fEdgeType(edgeType) {
35 this->initClassID<AARectEffect>();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000036 this->setWillReadFragmentPosition();
37 }
38
mtklein36352bf2015-03-25 18:17:31 -070039 bool onIsEqual(const GrFragmentProcessor& other) const override {
joshualitt49586be2014-09-16 08:21:41 -070040 const AARectEffect& aare = other.cast<AARectEffect>();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000041 return fRect == aare.fRect;
42 }
43
mtklein36352bf2015-03-25 18:17:31 -070044 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
egdaniel1a8ecdf2014-10-03 06:24:12 -070045 if (fRect.isEmpty()) {
46 // An empty rect will have no coverage anywhere.
joshualitt56995b52014-12-11 15:44:02 -080047 inout->mulByKnownSingleComponent(0);
egdaniel1a8ecdf2014-10-03 06:24:12 -070048 } else {
joshualitt56995b52014-12-11 15:44:02 -080049 inout->mulByUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -070050 }
egdaniel1a8ecdf2014-10-03 06:24:12 -070051 }
52
joshualittb0a8a372014-09-23 09:50:21 -070053 SkRect fRect;
54 GrPrimitiveEdgeType fEdgeType;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +000055
joshualittb0a8a372014-09-23 09:50:21 -070056 typedef GrFragmentProcessor INHERITED;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000057
joshualittb0a8a372014-09-23 09:50:21 -070058 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000059
60};
61
joshualittb0a8a372014-09-23 09:50:21 -070062GR_DEFINE_FRAGMENT_PROCESSOR_TEST(AARectEffect);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000063
joshualittb0a8a372014-09-23 09:50:21 -070064GrFragmentProcessor* AARectEffect::TestCreate(SkRandom* random,
65 GrContext*,
66 const GrDrawTargetCaps& caps,
67 GrTexture*[]) {
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000068 SkRect rect = SkRect::MakeLTRB(random->nextSScalar1(),
69 random->nextSScalar1(),
70 random->nextSScalar1(),
71 random->nextSScalar1());
joshualittb0a8a372014-09-23 09:50:21 -070072 GrFragmentProcessor* fp;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000073 do {
joshualittb0a8a372014-09-23 09:50:21 -070074 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(random->nextULessThan(
75 kGrProcessorEdgeTypeCnt));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000076
joshualittb0a8a372014-09-23 09:50:21 -070077 fp = AARectEffect::Create(edgeType, rect);
78 } while (NULL == fp);
79 return fp;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000080}
81
82//////////////////////////////////////////////////////////////////////////////
83
joshualittb0a8a372014-09-23 09:50:21 -070084class GLAARectEffect : public GrGLFragmentProcessor {
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000085public:
joshualitteb2a6762014-12-04 11:35:33 -080086 GLAARectEffect(const GrProcessor&);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000087
joshualitt15988992014-10-09 15:04:05 -070088 virtual void emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -070089 const GrFragmentProcessor& fp,
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000090 const char* outputColor,
91 const char* inputColor,
92 const TransformedCoordsArray&,
mtklein36352bf2015-03-25 18:17:31 -070093 const TextureSamplerArray&) override;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000094
joshualittb0a8a372014-09-23 09:50:21 -070095 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000096
mtklein36352bf2015-03-25 18:17:31 -070097 void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000098
99private:
kkinnunen7510b222014-07-30 00:04:16 -0700100 GrGLProgramDataManager::UniformHandle fRectUniform;
101 SkRect fPrevRect;
joshualittb0a8a372014-09-23 09:50:21 -0700102 typedef GrGLFragmentProcessor INHERITED;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000103};
104
joshualitteb2a6762014-12-04 11:35:33 -0800105GLAARectEffect::GLAARectEffect(const GrProcessor& effect) {
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000106 fPrevRect.fLeft = SK_ScalarNaN;
107}
108
joshualitt15988992014-10-09 15:04:05 -0700109void GLAARectEffect::emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -0700110 const GrFragmentProcessor& fp,
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000111 const char* outputColor,
112 const char* inputColor,
113 const TransformedCoordsArray&,
114 const TextureSamplerArray& samplers) {
joshualittb0a8a372014-09-23 09:50:21 -0700115 const AARectEffect& aare = fp.cast<AARectEffect>();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000116 const char *rectName;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000117 // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
118 // respectively.
joshualitt30ba4362014-08-21 20:18:45 -0700119 fRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000120 kVec4f_GrSLType,
bsalomon422f56f2014-12-09 10:18:12 -0800121 kDefault_GrSLPrecision,
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000122 "rect",
123 &rectName);
joshualitt30ba4362014-08-21 20:18:45 -0700124
joshualitt15988992014-10-09 15:04:05 -0700125 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
joshualitt30ba4362014-08-21 20:18:45 -0700126 const char* fragmentPos = fsBuilder->fragmentPosition();
joshualittb0a8a372014-09-23 09:50:21 -0700127 if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000128 // The amount of coverage removed in x and y by the edges is computed as a pair of negative
129 // numbers, xSub and ySub.
joshualitt30ba4362014-08-21 20:18:45 -0700130 fsBuilder->codeAppend("\t\tfloat xSub, ySub;\n");
131 fsBuilder->codeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName);
132 fsBuilder->codeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos);
133 fsBuilder->codeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName);
134 fsBuilder->codeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos);
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000135 // Now compute coverage in x and y and multiply them to get the fraction of the pixel
136 // covered.
joshualitt30ba4362014-08-21 20:18:45 -0700137 fsBuilder->codeAppendf("\t\tfloat alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0));\n");
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000138 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700139 fsBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
robertphillips7f14c9b2015-01-30 14:44:22 -0800140 fsBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
141 fsBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
142 fsBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
143 fsBuilder->codeAppendf("\t\talpha *= (%s.w - %s.y) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000144 }
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000145
joshualittb0a8a372014-09-23 09:50:21 -0700146 if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) {
joshualitt30ba4362014-08-21 20:18:45 -0700147 fsBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000148 }
joshualitt30ba4362014-08-21 20:18:45 -0700149 fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000150 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
151}
152
joshualittb0a8a372014-09-23 09:50:21 -0700153void GLAARectEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) {
154 const AARectEffect& aare = processor.cast<AARectEffect>();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000155 const SkRect& rect = aare.getRect();
156 if (rect != fPrevRect) {
robertphillips7f14c9b2015-01-30 14:44:22 -0800157 pdman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
158 rect.fRight - 0.5f, rect.fBottom - 0.5f);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000159 fPrevRect = rect;
160 }
161}
162
joshualittb0a8a372014-09-23 09:50:21 -0700163void GLAARectEffect::GenKey(const GrProcessor& processor, const GrGLCaps&,
164 GrProcessorKeyBuilder* b) {
165 const AARectEffect& aare = processor.cast<AARectEffect>();
bsalomon63e99f72014-07-21 08:03:14 -0700166 b->add32(aare.getEdgeType());
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000167}
168
joshualitteb2a6762014-12-04 11:35:33 -0800169void AARectEffect::getGLProcessorKey(const GrGLCaps& caps, GrProcessorKeyBuilder* b) const {
170 GLAARectEffect::GenKey(*this, caps, b);
171}
172
173GrGLFragmentProcessor* AARectEffect::createGLInstance() const {
174 return SkNEW_ARGS(GLAARectEffect, (*this));
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000175}
176
177//////////////////////////////////////////////////////////////////////////////
178
joshualittb0a8a372014-09-23 09:50:21 -0700179class GrGLConvexPolyEffect : public GrGLFragmentProcessor {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000180public:
joshualitteb2a6762014-12-04 11:35:33 -0800181 GrGLConvexPolyEffect(const GrProcessor&);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000182
joshualitt15988992014-10-09 15:04:05 -0700183 virtual void emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -0700184 const GrFragmentProcessor& fp,
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000185 const char* outputColor,
186 const char* inputColor,
187 const TransformedCoordsArray&,
mtklein36352bf2015-03-25 18:17:31 -0700188 const TextureSamplerArray&) override;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000189
joshualittb0a8a372014-09-23 09:50:21 -0700190 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000191
mtklein36352bf2015-03-25 18:17:31 -0700192 void setData(const GrGLProgramDataManager&, const GrProcessor&) override;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000193
194private:
kkinnunen7510b222014-07-30 00:04:16 -0700195 GrGLProgramDataManager::UniformHandle fEdgeUniform;
196 SkScalar fPrevEdges[3 * GrConvexPolyEffect::kMaxEdges];
joshualittb0a8a372014-09-23 09:50:21 -0700197 typedef GrGLFragmentProcessor INHERITED;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000198};
199
joshualitteb2a6762014-12-04 11:35:33 -0800200GrGLConvexPolyEffect::GrGLConvexPolyEffect(const GrProcessor&) {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000201 fPrevEdges[0] = SK_ScalarNaN;
202}
203
joshualitt15988992014-10-09 15:04:05 -0700204void GrGLConvexPolyEffect::emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -0700205 const GrFragmentProcessor& fp,
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000206 const char* outputColor,
207 const char* inputColor,
208 const TransformedCoordsArray&,
209 const TextureSamplerArray& samplers) {
joshualittb0a8a372014-09-23 09:50:21 -0700210 const GrConvexPolyEffect& cpe = fp.cast<GrConvexPolyEffect>();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000211
212 const char *edgeArrayName;
joshualitt30ba4362014-08-21 20:18:45 -0700213 fEdgeUniform = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000214 kVec3f_GrSLType,
bsalomon422f56f2014-12-09 10:18:12 -0800215 kDefault_GrSLPrecision,
216 "edges",
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000217 cpe.getEdgeCount(),
218 &edgeArrayName);
joshualitt15988992014-10-09 15:04:05 -0700219 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
joshualitt30ba4362014-08-21 20:18:45 -0700220 fsBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
221 fsBuilder->codeAppend("\t\tfloat edge;\n");
222 const char* fragmentPos = fsBuilder->fragmentPosition();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000223 for (int i = 0; i < cpe.getEdgeCount(); ++i) {
robertphillips7f14c9b2015-01-30 14:44:22 -0800224 fsBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n",
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000225 edgeArrayName, i, fragmentPos, fragmentPos);
joshualittb0a8a372014-09-23 09:50:21 -0700226 if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
joshualitt30ba4362014-08-21 20:18:45 -0700227 fsBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000228 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700229 fsBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000230 }
joshualitt30ba4362014-08-21 20:18:45 -0700231 fsBuilder->codeAppend("\t\talpha *= edge;\n");
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000232 }
233
commit-bot@chromium.org6dee8752014-02-07 22:39:01 +0000234 // Woe is me. See skbug.com/2149.
235 if (kTegra2_GrGLRenderer == builder->ctxInfo().renderer()) {
joshualitt30ba4362014-08-21 20:18:45 -0700236 fsBuilder->codeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n");
commit-bot@chromium.org6dee8752014-02-07 22:39:01 +0000237 }
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000238
joshualittb0a8a372014-09-23 09:50:21 -0700239 if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
joshualitt30ba4362014-08-21 20:18:45 -0700240 fsBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000241 }
joshualitt30ba4362014-08-21 20:18:45 -0700242 fsBuilder->codeAppendf("\t%s = %s;\n", outputColor,
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000243 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
244}
245
joshualittb0a8a372014-09-23 09:50:21 -0700246void GrGLConvexPolyEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& effect) {
joshualitt49586be2014-09-16 08:21:41 -0700247 const GrConvexPolyEffect& cpe = effect.cast<GrConvexPolyEffect>();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000248 size_t byteSize = 3 * cpe.getEdgeCount() * sizeof(SkScalar);
249 if (0 != memcmp(fPrevEdges, cpe.getEdges(), byteSize)) {
kkinnunen7510b222014-07-30 00:04:16 -0700250 pdman.set3fv(fEdgeUniform, cpe.getEdgeCount(), cpe.getEdges());
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000251 memcpy(fPrevEdges, cpe.getEdges(), byteSize);
252 }
253}
254
joshualittb0a8a372014-09-23 09:50:21 -0700255void GrGLConvexPolyEffect::GenKey(const GrProcessor& processor, const GrGLCaps&,
256 GrProcessorKeyBuilder* b) {
257 const GrConvexPolyEffect& cpe = processor.cast<GrConvexPolyEffect>();
258 GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8);
bsalomon63e99f72014-07-21 08:03:14 -0700259 uint32_t key = (cpe.getEdgeCount() << 3) | cpe.getEdgeType();
260 b->add32(key);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000261}
262
263//////////////////////////////////////////////////////////////////////////////
264
joshualittb0a8a372014-09-23 09:50:21 -0700265GrFragmentProcessor* GrConvexPolyEffect::Create(GrPrimitiveEdgeType type, const SkPath& path,
266 const SkVector* offset) {
267 if (kHairlineAA_GrProcessorEdgeType == type) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000268 return NULL;
269 }
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000270 if (path.getSegmentMasks() != SkPath::kLine_SegmentMask ||
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000271 !path.isConvex()) {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000272 return NULL;
273 }
274
275 if (path.countPoints() > kMaxEdges) {
276 return NULL;
277 }
278
279 SkPoint pts[kMaxEdges];
280 SkScalar edges[3 * kMaxEdges];
281
282 SkPath::Direction dir;
283 SkAssertResult(path.cheapComputeDirection(&dir));
284
commit-bot@chromium.orgb21fac12014-02-07 21:13:11 +0000285 SkVector t;
286 if (NULL == offset) {
287 t.set(0, 0);
288 } else {
289 t = *offset;
290 }
291
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000292 int count = path.getPoints(pts, kMaxEdges);
293 int n = 0;
294 for (int lastPt = count - 1, i = 0; i < count; lastPt = i++) {
295 if (pts[lastPt] != pts[i]) {
296 SkVector v = pts[i] - pts[lastPt];
297 v.normalize();
298 if (SkPath::kCCW_Direction == dir) {
299 edges[3 * n] = v.fY;
300 edges[3 * n + 1] = -v.fX;
301 } else {
302 edges[3 * n] = -v.fY;
303 edges[3 * n + 1] = v.fX;
304 }
commit-bot@chromium.orgb21fac12014-02-07 21:13:11 +0000305 SkPoint p = pts[i] + t;
306 edges[3 * n + 2] = -(edges[3 * n] * p.fX + edges[3 * n + 1] * p.fY);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000307 ++n;
308 }
309 }
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000310 if (path.isInverseFillType()) {
joshualittb0a8a372014-09-23 09:50:21 -0700311 type = GrInvertProcessorEdgeType(type);
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000312 }
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000313 return Create(type, n, edges);
314}
315
joshualittb0a8a372014-09-23 09:50:21 -0700316GrFragmentProcessor* GrConvexPolyEffect::Create(GrPrimitiveEdgeType edgeType, const SkRect& rect) {
317 if (kHairlineAA_GrProcessorEdgeType == edgeType){
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000318 return NULL;
319 }
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000320 return AARectEffect::Create(edgeType, rect);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000321}
322
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000323GrConvexPolyEffect::~GrConvexPolyEffect() {}
324
egdaniel605dd0f2014-11-12 08:35:25 -0800325void GrConvexPolyEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
joshualitt56995b52014-12-11 15:44:02 -0800326 inout->mulByUnknownSingleComponent();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000327}
328
joshualitteb2a6762014-12-04 11:35:33 -0800329void GrConvexPolyEffect::getGLProcessorKey(const GrGLCaps& caps,
330 GrProcessorKeyBuilder* b) const {
331 GrGLConvexPolyEffect::GenKey(*this, caps, b);
332}
333
334GrGLFragmentProcessor* GrConvexPolyEffect::createGLInstance() const {
335 return SkNEW_ARGS(GrGLConvexPolyEffect, (*this));
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000336}
337
joshualittb0a8a372014-09-23 09:50:21 -0700338GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[])
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000339 : fEdgeType(edgeType)
340 , fEdgeCount(n) {
joshualitteb2a6762014-12-04 11:35:33 -0800341 this->initClassID<GrConvexPolyEffect>();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000342 // 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
bsalomon0e08fc12014-10-15 08:19:04 -0700353bool GrConvexPolyEffect::onIsEqual(const GrFragmentProcessor& other) const {
joshualitt49586be2014-09-16 08:21:41 -0700354 const GrConvexPolyEffect& cpe = other.cast<GrConvexPolyEffect>();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000355 // 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
joshualittb0a8a372014-09-23 09:50:21 -0700362GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConvexPolyEffect);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000363
joshualittb0a8a372014-09-23 09:50:21 -0700364GrFragmentProcessor* GrConvexPolyEffect::TestCreate(SkRandom* random,
365 GrContext*,
366 const GrDrawTargetCaps& caps,
367 GrTexture*[]) {
commit-bot@chromium.org65ee5f42014-02-04 17:49:48 +0000368 int count = random->nextULessThan(kMaxEdges) + 1;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000369 SkScalar edges[kMaxEdges * 3];
370 for (int i = 0; i < 3 * count; ++i) {
371 edges[i] = random->nextSScalar1();
372 }
373
joshualittb0a8a372014-09-23 09:50:21 -0700374 GrFragmentProcessor* fp;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000375 do {
joshualittb0a8a372014-09-23 09:50:21 -0700376 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
377 random->nextULessThan(kGrProcessorEdgeTypeCnt));
378 fp = GrConvexPolyEffect::Create(edgeType, count, edges);
379 } while (NULL == fp);
380 return fp;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000381}