blob: da77eb8c05d124d5228ed01c378fc16c0c8428db [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"
reed026beb52015-06-10 14:23:15 -070010#include "SkPathPriv.h"
bsalomon7888de02016-03-28 15:04:45 -070011#include "effects/GrConstColorProcessor.h"
egdaniel64c47282015-11-13 06:54:19 -080012#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080013#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070014#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080015#include "glsl/GrGLSLUniformHandler.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050016#include "../private/GrGLSL.h"
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000017
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000018//////////////////////////////////////////////////////////////////////////////
joshualittb0a8a372014-09-23 09:50:21 -070019class AARectEffect : public GrFragmentProcessor {
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000020public:
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000021 const SkRect& getRect() const { return fRect; }
22
bungeman06ca8ec2016-06-09 08:01:03 -070023 static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType edgeType, const SkRect& rect) {
24 return sk_sp<GrFragmentProcessor>(new AARectEffect(edgeType, rect));
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000025 }
26
joshualittb0a8a372014-09-23 09:50:21 -070027 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +000028
mtklein36352bf2015-03-25 18:17:31 -070029 const char* name() const override { return "AARect"; }
joshualitteb2a6762014-12-04 11:35:33 -080030
Brian Salomon94efbf52016-11-29 13:43:05 -050031 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
joshualitteb2a6762014-12-04 11:35:33 -080032
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000033private:
joshualitteb2a6762014-12-04 11:35:33 -080034 AARectEffect(GrPrimitiveEdgeType edgeType, const SkRect& rect)
Brian Salomon587e08f2017-01-27 10:59:27 -050035 : INHERITED(kModulatesInput_OptimizationFlag), fRect(rect), fEdgeType(edgeType) {
joshualitteb2a6762014-12-04 11:35:33 -080036 this->initClassID<AARectEffect>();
Ethan Nicholascae3a4c2017-02-02 10:43:58 -050037 this->setWillReadFragmentPosition();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000038 }
39
egdaniel57d3b032015-11-13 11:57:27 -080040 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -070041
mtklein36352bf2015-03-25 18:17:31 -070042 bool onIsEqual(const GrFragmentProcessor& other) const override {
joshualitt49586be2014-09-16 08:21:41 -070043 const AARectEffect& aare = other.cast<AARectEffect>();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000044 return fRect == aare.fRect;
45 }
46
mtklein36352bf2015-03-25 18:17:31 -070047 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
egdaniel1a8ecdf2014-10-03 06:24:12 -070048 if (fRect.isEmpty()) {
49 // An empty rect will have no coverage anywhere.
joshualitt56995b52014-12-11 15:44:02 -080050 inout->mulByKnownSingleComponent(0);
egdaniel1a8ecdf2014-10-03 06:24:12 -070051 } else {
joshualitt56995b52014-12-11 15:44:02 -080052 inout->mulByUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -070053 }
egdaniel1a8ecdf2014-10-03 06:24:12 -070054 }
55
joshualittb0a8a372014-09-23 09:50:21 -070056 SkRect fRect;
57 GrPrimitiveEdgeType fEdgeType;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +000058
joshualittb0a8a372014-09-23 09:50:21 -070059 typedef GrFragmentProcessor INHERITED;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000060
joshualittb0a8a372014-09-23 09:50:21 -070061 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000062
63};
64
joshualittb0a8a372014-09-23 09:50:21 -070065GR_DEFINE_FRAGMENT_PROCESSOR_TEST(AARectEffect);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000066
Hal Canary6f6961e2017-01-31 13:50:44 -050067#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -070068sk_sp<GrFragmentProcessor> AARectEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -070069 SkRect rect = SkRect::MakeLTRB(d->fRandom->nextSScalar1(),
70 d->fRandom->nextSScalar1(),
71 d->fRandom->nextSScalar1(),
72 d->fRandom->nextSScalar1());
bungeman06ca8ec2016-06-09 08:01:03 -070073 sk_sp<GrFragmentProcessor> fp;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000074 do {
joshualitt0067ff52015-07-08 14:26:19 -070075 GrPrimitiveEdgeType edgeType = static_cast<GrPrimitiveEdgeType>(
76 d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000077
bungeman06ca8ec2016-06-09 08:01:03 -070078 fp = AARectEffect::Make(edgeType, rect);
halcanary96fcdcc2015-08-27 07:41:13 -070079 } while (nullptr == fp);
joshualittb0a8a372014-09-23 09:50:21 -070080 return fp;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000081}
Hal Canary6f6961e2017-01-31 13:50:44 -050082#endif
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000083
84//////////////////////////////////////////////////////////////////////////////
85
egdaniel64c47282015-11-13 06:54:19 -080086class GLAARectEffect : public GrGLSLFragmentProcessor {
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000087public:
robertphillips9cdb9922016-02-03 12:25:40 -080088 GLAARectEffect() {
89 fPrevRect.fLeft = SK_ScalarNaN;
90 }
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000091
robertphillips9cdb9922016-02-03 12:25:40 -080092 void emitCode(EmitArgs&) override;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000093
Brian Salomon94efbf52016-11-29 13:43:05 -050094 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000095
wangyixb1daa862015-08-18 11:29:31 -070096protected:
egdaniel018fb622015-10-28 07:26:40 -070097 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +000098
99private:
egdaniel018fb622015-10-28 07:26:40 -0700100 GrGLSLProgramDataManager::UniformHandle fRectUniform;
robertphillipsbf536af2016-02-04 06:11:53 -0800101 SkRect fPrevRect;
102
egdaniel64c47282015-11-13 06:54:19 -0800103 typedef GrGLSLFragmentProcessor INHERITED;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000104};
105
wangyix7c157a92015-07-22 15:08:53 -0700106void GLAARectEffect::emitCode(EmitArgs& args) {
107 const AARectEffect& aare = args.fFp.cast<AARectEffect>();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000108 const char *rectName;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000109 // The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
110 // respectively.
cdalton5e58cee2016-02-11 12:49:47 -0800111 fRectUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800112 kVec4f_GrSLType,
113 kDefault_GrSLPrecision,
114 "rect",
115 &rectName);
joshualitt30ba4362014-08-21 20:18:45 -0700116
cdalton85285412016-02-18 12:37:07 -0800117 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Ethan Nicholascae3a4c2017-02-02 10:43:58 -0500118 const char* fragmentPos = fragBuilder->fragmentPosition();
joshualittb0a8a372014-09-23 09:50:21 -0700119 if (GrProcessorEdgeTypeIsAA(aare.getEdgeType())) {
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000120 // The amount of coverage removed in x and y by the edges is computed as a pair of negative
121 // numbers, xSub and ySub.
egdaniel4ca2e602015-11-18 08:01:26 -0800122 fragBuilder->codeAppend("\t\tfloat xSub, ySub;\n");
Ethan Nicholascae3a4c2017-02-02 10:43:58 -0500123 fragBuilder->codeAppendf("\t\txSub = min(%s.x - %s.x, 0.0);\n", fragmentPos, rectName);
124 fragBuilder->codeAppendf("\t\txSub += min(%s.z - %s.x, 0.0);\n", rectName, fragmentPos);
125 fragBuilder->codeAppendf("\t\tySub = min(%s.y - %s.y, 0.0);\n", fragmentPos, rectName);
126 fragBuilder->codeAppendf("\t\tySub += min(%s.w - %s.y, 0.0);\n", rectName, fragmentPos);
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000127 // Now compute coverage in x and y and multiply them to get the fraction of the pixel
128 // covered.
egdaniel4ca2e602015-11-18 08:01:26 -0800129 fragBuilder->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 +0000130 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800131 fragBuilder->codeAppendf("\t\tfloat alpha = 1.0;\n");
Ethan Nicholascae3a4c2017-02-02 10:43:58 -0500132 fragBuilder->codeAppendf("\t\talpha *= (%s.x - %s.x) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
133 fragBuilder->codeAppendf("\t\talpha *= (%s.z - %s.x) > -0.5 ? 1.0 : 0.0;\n", rectName, fragmentPos);
134 fragBuilder->codeAppendf("\t\talpha *= (%s.y - %s.y) > -0.5 ? 1.0 : 0.0;\n", fragmentPos, rectName);
135 fragBuilder->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 +0000136 }
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000137
joshualittb0a8a372014-09-23 09:50:21 -0700138 if (GrProcessorEdgeTypeIsInverseFill(aare.getEdgeType())) {
egdaniel4ca2e602015-11-18 08:01:26 -0800139 fragBuilder->codeAppend("\t\talpha = 1.0 - alpha;\n");
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000140 }
egdaniel4ca2e602015-11-18 08:01:26 -0800141 fragBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
142 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000143}
144
egdaniel018fb622015-10-28 07:26:40 -0700145void GLAARectEffect::onSetData(const GrGLSLProgramDataManager& pdman,
146 const GrProcessor& processor) {
joshualittb0a8a372014-09-23 09:50:21 -0700147 const AARectEffect& aare = processor.cast<AARectEffect>();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000148 const SkRect& rect = aare.getRect();
149 if (rect != fPrevRect) {
robertphillips7f14c9b2015-01-30 14:44:22 -0800150 pdman.set4f(fRectUniform, rect.fLeft + 0.5f, rect.fTop + 0.5f,
151 rect.fRight - 0.5f, rect.fBottom - 0.5f);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000152 fPrevRect = rect;
153 }
154}
155
Brian Salomon94efbf52016-11-29 13:43:05 -0500156void GLAARectEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700157 GrProcessorKeyBuilder* b) {
158 const AARectEffect& aare = processor.cast<AARectEffect>();
bsalomon63e99f72014-07-21 08:03:14 -0700159 b->add32(aare.getEdgeType());
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000160}
161
Brian Salomon94efbf52016-11-29 13:43:05 -0500162void AARectEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
joshualitteb2a6762014-12-04 11:35:33 -0800163 GLAARectEffect::GenKey(*this, caps, b);
164}
165
egdaniel57d3b032015-11-13 11:57:27 -0800166GrGLSLFragmentProcessor* AARectEffect::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800167 return new GLAARectEffect;
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000168}
169
170//////////////////////////////////////////////////////////////////////////////
171
egdaniel64c47282015-11-13 06:54:19 -0800172class GrGLConvexPolyEffect : public GrGLSLFragmentProcessor {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000173public:
robertphillips9cdb9922016-02-03 12:25:40 -0800174 GrGLConvexPolyEffect() {
175 fPrevEdges[0] = SK_ScalarNaN;
176 }
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000177
robertphillips9cdb9922016-02-03 12:25:40 -0800178 void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000179
Brian Salomon94efbf52016-11-29 13:43:05 -0500180 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000181
wangyixb1daa862015-08-18 11:29:31 -0700182protected:
egdaniel018fb622015-10-28 07:26:40 -0700183 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000184
185private:
egdaniel018fb622015-10-28 07:26:40 -0700186 GrGLSLProgramDataManager::UniformHandle fEdgeUniform;
robertphillipsbf536af2016-02-04 06:11:53 -0800187 SkScalar fPrevEdges[3 * GrConvexPolyEffect::kMaxEdges];
egdaniel64c47282015-11-13 06:54:19 -0800188 typedef GrGLSLFragmentProcessor INHERITED;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000189};
190
wangyix7c157a92015-07-22 15:08:53 -0700191void GrGLConvexPolyEffect::emitCode(EmitArgs& args) {
192 const GrConvexPolyEffect& cpe = args.fFp.cast<GrConvexPolyEffect>();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000193
194 const char *edgeArrayName;
cdalton5e58cee2016-02-11 12:49:47 -0800195 fEdgeUniform = args.fUniformHandler->addUniformArray(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800196 kVec3f_GrSLType,
197 kDefault_GrSLPrecision,
198 "edges",
199 cpe.getEdgeCount(),
200 &edgeArrayName);
cdalton85285412016-02-18 12:37:07 -0800201 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
egdaniel4ca2e602015-11-18 08:01:26 -0800202 fragBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
203 fragBuilder->codeAppend("\t\tfloat edge;\n");
Ethan Nicholascae3a4c2017-02-02 10:43:58 -0500204 const char* fragmentPos = fragBuilder->fragmentPosition();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000205 for (int i = 0; i < cpe.getEdgeCount(); ++i) {
Ethan Nicholascae3a4c2017-02-02 10:43:58 -0500206 fragBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n",
207 edgeArrayName, i, fragmentPos, fragmentPos);
joshualittb0a8a372014-09-23 09:50:21 -0700208 if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
egdaniel4ca2e602015-11-18 08:01:26 -0800209 fragBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000210 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800211 fragBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000212 }
egdaniel4ca2e602015-11-18 08:01:26 -0800213 fragBuilder->codeAppend("\t\talpha *= edge;\n");
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000214 }
215
joshualittb0a8a372014-09-23 09:50:21 -0700216 if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
egdaniel4ca2e602015-11-18 08:01:26 -0800217 fragBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000218 }
egdaniel4ca2e602015-11-18 08:01:26 -0800219 fragBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor,
220 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000221}
222
egdaniel018fb622015-10-28 07:26:40 -0700223void GrGLConvexPolyEffect::onSetData(const GrGLSLProgramDataManager& pdman,
224 const GrProcessor& effect) {
joshualitt49586be2014-09-16 08:21:41 -0700225 const GrConvexPolyEffect& cpe = effect.cast<GrConvexPolyEffect>();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000226 size_t byteSize = 3 * cpe.getEdgeCount() * sizeof(SkScalar);
227 if (0 != memcmp(fPrevEdges, cpe.getEdges(), byteSize)) {
kkinnunen7510b222014-07-30 00:04:16 -0700228 pdman.set3fv(fEdgeUniform, cpe.getEdgeCount(), cpe.getEdges());
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000229 memcpy(fPrevEdges, cpe.getEdges(), byteSize);
230 }
231}
232
Brian Salomon94efbf52016-11-29 13:43:05 -0500233void GrGLConvexPolyEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700234 GrProcessorKeyBuilder* b) {
235 const GrConvexPolyEffect& cpe = processor.cast<GrConvexPolyEffect>();
236 GR_STATIC_ASSERT(kGrProcessorEdgeTypeCnt <= 8);
bsalomon63e99f72014-07-21 08:03:14 -0700237 uint32_t key = (cpe.getEdgeCount() << 3) | cpe.getEdgeType();
238 b->add32(key);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000239}
240
241//////////////////////////////////////////////////////////////////////////////
242
bungeman06ca8ec2016-06-09 08:01:03 -0700243sk_sp<GrFragmentProcessor> GrConvexPolyEffect::Make(GrPrimitiveEdgeType type, const SkPath& path,
244 const SkVector* offset) {
joshualittb0a8a372014-09-23 09:50:21 -0700245 if (kHairlineAA_GrProcessorEdgeType == type) {
halcanary96fcdcc2015-08-27 07:41:13 -0700246 return nullptr;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000247 }
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000248 if (path.getSegmentMasks() != SkPath::kLine_SegmentMask ||
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000249 !path.isConvex()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700250 return nullptr;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000251 }
252
reed026beb52015-06-10 14:23:15 -0700253 SkPathPriv::FirstDirection dir;
bsalomon7888de02016-03-28 15:04:45 -0700254 // The only way this should fail is if the clip is effectively a infinitely thin line. In that
255 // case nothing is inside the clip. It'd be nice to detect this at a higher level and either
256 // skip the draw or omit the clip element.
257 if (!SkPathPriv::CheapComputeFirstDirection(path, &dir)) {
258 if (GrProcessorEdgeTypeIsInverseFill(type)) {
Brian Osman618d3042016-10-25 10:51:28 -0400259 return GrConstColorProcessor::Make(GrColor4f::OpaqueWhite(),
bungeman06ca8ec2016-06-09 08:01:03 -0700260 GrConstColorProcessor::kModulateRGBA_InputMode);
bsalomon7888de02016-03-28 15:04:45 -0700261 }
Brian Osman618d3042016-10-25 10:51:28 -0400262 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
263 GrConstColorProcessor::kIgnore_InputMode);
bsalomon7888de02016-03-28 15:04:45 -0700264 }
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000265
commit-bot@chromium.orgb21fac12014-02-07 21:13:11 +0000266 SkVector t;
halcanary96fcdcc2015-08-27 07:41:13 -0700267 if (nullptr == offset) {
commit-bot@chromium.orgb21fac12014-02-07 21:13:11 +0000268 t.set(0, 0);
269 } else {
270 t = *offset;
271 }
272
lsalzmand15947e2016-05-31 09:46:00 -0700273 SkScalar edges[3 * kMaxEdges];
274 SkPoint pts[4];
275 SkPath::Verb verb;
276 SkPath::Iter iter(path, true);
277
278 // SkPath considers itself convex so long as there is a convex contour within it,
279 // regardless of any degenerate contours such as a string of moveTos before it.
280 // Iterate here to consume any degenerate contours and only process the points
281 // on the actual convex contour.
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000282 int n = 0;
lsalzmand15947e2016-05-31 09:46:00 -0700283 while ((verb = iter.next(pts, true, true)) != SkPath::kDone_Verb) {
284 switch (verb) {
285 case SkPath::kMove_Verb:
286 SkASSERT(n == 0);
287 case SkPath::kClose_Verb:
288 break;
289 case SkPath::kLine_Verb: {
290 if (n >= kMaxEdges) {
291 return nullptr;
292 }
293 SkVector v = pts[1] - pts[0];
294 v.normalize();
295 if (SkPathPriv::kCCW_FirstDirection == dir) {
296 edges[3 * n] = v.fY;
297 edges[3 * n + 1] = -v.fX;
298 } else {
299 edges[3 * n] = -v.fY;
300 edges[3 * n + 1] = v.fX;
301 }
302 SkPoint p = pts[1] + t;
303 edges[3 * n + 2] = -(edges[3 * n] * p.fX + edges[3 * n + 1] * p.fY);
304 ++n;
305 break;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000306 }
lsalzmand15947e2016-05-31 09:46:00 -0700307 default:
308 return nullptr;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000309 }
310 }
lsalzmand15947e2016-05-31 09:46:00 -0700311
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000312 if (path.isInverseFillType()) {
joshualittb0a8a372014-09-23 09:50:21 -0700313 type = GrInvertProcessorEdgeType(type);
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000314 }
bungeman06ca8ec2016-06-09 08:01:03 -0700315 return Make(type, n, edges);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000316}
317
bungeman06ca8ec2016-06-09 08:01:03 -0700318sk_sp<GrFragmentProcessor> GrConvexPolyEffect::Make(GrPrimitiveEdgeType edgeType,
319 const SkRect& rect) {
joshualittb0a8a372014-09-23 09:50:21 -0700320 if (kHairlineAA_GrProcessorEdgeType == edgeType){
halcanary96fcdcc2015-08-27 07:41:13 -0700321 return nullptr;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000322 }
bungeman06ca8ec2016-06-09 08:01:03 -0700323 return AARectEffect::Make(edgeType, rect);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000324}
325
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000326GrConvexPolyEffect::~GrConvexPolyEffect() {}
327
egdaniel605dd0f2014-11-12 08:35:25 -0800328void GrConvexPolyEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
joshualitt56995b52014-12-11 15:44:02 -0800329 inout->mulByUnknownSingleComponent();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000330}
331
Brian Salomon94efbf52016-11-29 13:43:05 -0500332void GrConvexPolyEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800333 GrProcessorKeyBuilder* b) const {
joshualitteb2a6762014-12-04 11:35:33 -0800334 GrGLConvexPolyEffect::GenKey(*this, caps, b);
335}
336
egdaniel57d3b032015-11-13 11:57:27 -0800337GrGLSLFragmentProcessor* GrConvexPolyEffect::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800338 return new GrGLConvexPolyEffect;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000339}
340
joshualittb0a8a372014-09-23 09:50:21 -0700341GrConvexPolyEffect::GrConvexPolyEffect(GrPrimitiveEdgeType edgeType, int n, const SkScalar edges[])
Brian Salomon587e08f2017-01-27 10:59:27 -0500342 : INHERITED(kModulatesInput_OptimizationFlag), fEdgeType(edgeType), fEdgeCount(n) {
joshualitteb2a6762014-12-04 11:35:33 -0800343 this->initClassID<GrConvexPolyEffect>();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000344 // Factory function should have already ensured this.
345 SkASSERT(n <= kMaxEdges);
346 memcpy(fEdges, edges, 3 * n * sizeof(SkScalar));
347 // Outset the edges by 0.5 so that a pixel with center on an edge is 50% covered in the AA case
348 // and 100% covered in the non-AA case.
349 for (int i = 0; i < n; ++i) {
350 fEdges[3 * i + 2] += SK_ScalarHalf;
351 }
Ethan Nicholascae3a4c2017-02-02 10:43:58 -0500352 this->setWillReadFragmentPosition();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000353}
354
bsalomon0e08fc12014-10-15 08:19:04 -0700355bool GrConvexPolyEffect::onIsEqual(const GrFragmentProcessor& other) const {
joshualitt49586be2014-09-16 08:21:41 -0700356 const GrConvexPolyEffect& cpe = other.cast<GrConvexPolyEffect>();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000357 // ignore the fact that 0 == -0 and just use memcmp.
358 return (cpe.fEdgeType == fEdgeType && cpe.fEdgeCount == fEdgeCount &&
359 0 == memcmp(cpe.fEdges, fEdges, 3 * fEdgeCount * sizeof(SkScalar)));
360}
361
362//////////////////////////////////////////////////////////////////////////////
363
joshualittb0a8a372014-09-23 09:50:21 -0700364GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConvexPolyEffect);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000365
Hal Canary6f6961e2017-01-31 13:50:44 -0500366#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700367sk_sp<GrFragmentProcessor> GrConvexPolyEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700368 int count = d->fRandom->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) {
joshualitt0067ff52015-07-08 14:26:19 -0700371 edges[i] = d->fRandom->nextSScalar1();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000372 }
373
bungeman06ca8ec2016-06-09 08:01:03 -0700374 sk_sp<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>(
joshualitt0067ff52015-07-08 14:26:19 -0700377 d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt));
bungeman06ca8ec2016-06-09 08:01:03 -0700378 fp = GrConvexPolyEffect::Make(edgeType, count, edges);
halcanary96fcdcc2015-08-27 07:41:13 -0700379 } while (nullptr == fp);
joshualittb0a8a372014-09-23 09:50:21 -0700380 return fp;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000381}
Hal Canary6f6961e2017-01-31 13:50:44 -0500382#endif