blob: 51e8415556fff2be230cf921d29f301bfa65c196 [file] [log] [blame]
commit-bot@chromium.org78a10782013-08-21 19:27:48 +00001/*
2 * Copyright 2013 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// This test only works with the GPU backend.
9
10#include "gm.h"
Chris Dalton1d4af542018-04-16 14:23:00 -060011#include "sk_tool_utils.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000012
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000013#if SK_SUPPORT_GPU
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000014
15#include "GrContext.h"
Brian Salomon477d0ef2017-07-14 10:12:26 -040016#include "GrOpFlushState.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000017#include "GrPathUtils.h"
Brian Salomon477d0ef2017-07-14 10:12:26 -040018#include "GrRenderTargetContextPriv.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000019#include "GrTest.h"
20#include "SkColorPriv.h"
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000021#include "SkGeometry.h"
Cary Clarke4442cb2017-10-18 11:46:18 -040022#include "SkPoint3.h"
Cary Clark74f623d2017-11-06 20:02:02 -050023#include "SkPointPriv.h"
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000024#include "effects/GrBezierEffect.h"
Brian Salomon477d0ef2017-07-14 10:12:26 -040025#include "ops/GrMeshDrawOp.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000026
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000027namespace skiagm {
joshualitt95964c62015-02-11 13:45:50 -080028
Brian Salomon477d0ef2017-07-14 10:12:26 -040029class BezierTestOp : public GrMeshDrawOp {
30public:
31 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
32
Brian Osman9a725dd2017-09-20 09:53:22 -040033 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip,
34 GrPixelConfigIsClamped dstIsClamped) override {
Brian Salomon477d0ef2017-07-14 10:12:26 -040035 auto analysis = fProcessorSet.finalize(fColor, GrProcessorAnalysisCoverage::kSingleChannel,
Brian Osman9a725dd2017-09-20 09:53:22 -040036 clip, false, caps, dstIsClamped, &fColor);
Brian Salomon477d0ef2017-07-14 10:12:26 -040037 return analysis.requiresDstTexture() ? RequiresDstTexture::kYes : RequiresDstTexture::kNo;
38 }
39
Robert Phillipsf1748f52017-09-14 14:11:24 -040040 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -040041 fProcessorSet.visitProxies(func);
42 }
43
Brian Salomon477d0ef2017-07-14 10:12:26 -040044protected:
45 BezierTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color, int32_t classID)
46 : INHERITED(classID)
47 , fRect(rect)
48 , fColor(color)
49 , fGeometryProcessor(std::move(gp))
50 , fProcessorSet(SkBlendMode::kSrc) {
51 this->setBounds(rect, HasAABloat::kYes, IsZeroArea::kNo);
52 }
53
Brian Salomon91326c32017-08-09 16:02:19 -040054 const GrPipeline* makePipeline(Target* target) {
Brian Salomonbfd18cd2017-08-09 16:27:09 -040055 return target->makePipeline(0, std::move(fProcessorSet), target->detachAppliedClip());
Brian Salomon477d0ef2017-07-14 10:12:26 -040056 }
57
58 const GrGeometryProcessor* gp() const { return fGeometryProcessor.get(); }
59
60 const SkRect& rect() const { return fRect; }
61 GrColor color() const { return fColor; }
62
63private:
64 bool onCombineIfPossible(GrOp* op, const GrCaps& caps) override { return false; }
65
66 SkRect fRect;
67 GrColor fColor;
68 sk_sp<GrGeometryProcessor> fGeometryProcessor;
69 GrProcessorSet fProcessorSet;
70
71 typedef GrMeshDrawOp INHERITED;
72};
73
74class BezierCubicTestOp : public BezierTestOp {
joshualitt95964c62015-02-11 13:45:50 -080075public:
Brian Salomon25a88092016-12-01 09:36:50 -050076 DEFINE_OP_CLASS_ID
joshualitt95964c62015-02-11 13:45:50 -080077
Chris Daltonfebbffa2017-06-08 13:12:02 -060078 const char* name() const override { return "BezierCubicTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -080079
Brian Salomon477d0ef2017-07-14 10:12:26 -040080 static std::unique_ptr<GrDrawOp> Make(sk_sp<GrGeometryProcessor> gp, const SkRect& rect,
81 GrColor color) {
82 return std::unique_ptr<GrDrawOp>(new BezierCubicTestOp(std::move(gp), rect, color));
Brian Salomon6b316e92016-12-16 09:35:49 -050083 }
84
85private:
Chris Daltonfebbffa2017-06-08 13:12:02 -060086 BezierCubicTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color)
Brian Salomon477d0ef2017-07-14 10:12:26 -040087 : INHERITED(std::move(gp), rect, color, ClassID()) {}
joshualitt95964c62015-02-11 13:45:50 -080088
Brian Salomon91326c32017-08-09 16:02:19 -040089 void onPrepareDraws(Target* target) override {
bsalomonb5238a72015-05-05 07:49:49 -070090 QuadHelper helper;
Brian Salomon477d0ef2017-07-14 10:12:26 -040091 size_t vertexStride = this->gp()->getVertexStride();
Chris Daltonfebbffa2017-06-08 13:12:02 -060092 SkASSERT(vertexStride == sizeof(SkPoint));
93 SkPoint* pts = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1));
94 if (!pts) {
joshualitt4b31de82015-03-05 14:33:41 -080095 return;
96 }
Brian Salomon477d0ef2017-07-14 10:12:26 -040097 SkRect rect = this->rect();
Brian Salomonec42e152018-05-18 12:52:22 -040098 SkPointPriv::SetRectTriStrip(pts, rect, vertexStride);
Brian Salomon477d0ef2017-07-14 10:12:26 -040099 helper.recordDraw(target, this->gp(), this->makePipeline(target));
joshualitt95964c62015-02-11 13:45:50 -0800100 }
101
mtkleindbfd7ab2016-09-01 11:24:54 -0700102 static constexpr int kVertsPerCubic = 4;
103 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800104
Brian Salomon477d0ef2017-07-14 10:12:26 -0400105 typedef BezierTestOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800106};
107
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000108/**
109 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
110 */
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000111class BezierCubicEffects : public GM {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000112public:
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000113 BezierCubicEffects() {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000114 this->setBGColor(0xFFFFFFFF);
115 }
116
117protected:
mtklein36352bf2015-03-25 18:17:31 -0700118 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000119 return SkString("bezier_cubic_effects");
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000120 }
121
mtklein36352bf2015-03-25 18:17:31 -0700122 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700123 return SkISize::Make(800, 800);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000124 }
125
mtklein36352bf2015-03-25 18:17:31 -0700126 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400127 GrRenderTargetContext* renderTargetContext =
128 canvas->internal_private_accessTopLayerRenderTargetContext();
129 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700130 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000131 return;
132 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000133
robertphillips175dd9b2016-04-28 14:32:04 -0700134 GrContext* context = canvas->getGrContext();
135 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800136 return;
137 }
138
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400139 if (!context->contextPriv().caps()->shaderCaps()->floatIs32Bits()) {
Chris Dalton1d4af542018-04-16 14:23:00 -0600140 SkPaint paint;
141 sk_tool_utils::set_portable_typeface(&paint);
142 paint.setAntiAlias(true);
143 paint.setTextSize(20);
144
145 canvas->clear(SK_ColorWHITE);
146 canvas->drawString("float != fp32", 20, 40, paint);
147 return;
148 }
149
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000150 struct Vertex {
151 SkPoint fPosition;
152 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
153 };
154
mtkleindbfd7ab2016-09-01 11:24:54 -0700155 constexpr int kNumCubics = 15;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000156 SkRandom rand;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000157
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000158 // Mult by 3 for each edge effect type
159 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
160 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400161 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
162 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000163 int row = 0;
164 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700165 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000166
167 for (int i = 0; i < kNumCubics; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000168 SkPoint baseControlPts[] = {
169 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
170 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
171 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
172 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000173 };
Ethan Nicholas1706f842017-11-10 11:58:19 -0500174 for(GrClipEdgeType edgeType : {GrClipEdgeType::kFillBW,
175 GrClipEdgeType::kFillAA,
176 GrClipEdgeType::kHairlineAA}) {
Mike Reeddf85c382017-02-14 10:59:19 -0500177 SkScalar x = col * w;
178 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000179 SkPoint controlPts[] = {
180 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
181 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
182 {x + baseControlPts[2].fX, y + baseControlPts[2].fY},
183 {x + baseControlPts[3].fX, y + baseControlPts[3].fY}
184 };
185 SkPoint chopped[10];
csmartdaltoncc261272017-03-23 13:38:45 -0600186 SkMatrix klm;
Greg Daniel8199d942017-03-14 10:20:24 -0400187 int loopIndex;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000188 int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
189 chopped,
csmartdaltoncc261272017-03-23 13:38:45 -0600190 &klm,
Greg Daniel8199d942017-03-14 10:20:24 -0400191 &loopIndex);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000192
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000193 SkPaint ctrlPtPaint;
194 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
Hal Canary23e474c2017-05-15 13:35:35 -0400195 canvas->drawCircle(controlPts[0], 8.f, ctrlPtPaint);
Greg Daniel8199d942017-03-14 10:20:24 -0400196 for (int i = 1; i < 4; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400197 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000198 }
199
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000200 SkPaint polyPaint;
201 polyPaint.setColor(0xffA0A0A0);
202 polyPaint.setStrokeWidth(0);
203 polyPaint.setStyle(SkPaint::kStroke_Style);
204 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000205
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000206 SkPaint choppedPtPaint;
207 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000208
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000209 for (int c = 0; c < cnt; ++c) {
210 SkPoint* pts = chopped + 3 * c;
211
212 for (int i = 0; i < 4; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400213 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000214 }
215
216 SkRect bounds;
217 bounds.set(pts, 4);
218
219 SkPaint boundsPaint;
220 boundsPaint.setColor(0xff808080);
221 boundsPaint.setStrokeWidth(0);
222 boundsPaint.setStyle(SkPaint::kStroke_Style);
223 canvas->drawRect(bounds, boundsPaint);
224
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000225
Chris Daltonfebbffa2017-06-08 13:12:02 -0600226 bool flipKL = (c == loopIndex && cnt != 3);
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400227 sk_sp<GrGeometryProcessor> gp =
228 GrCubicEffect::Make(color, SkMatrix::I(), klm, flipKL, edgeType,
229 *context->contextPriv().caps());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600230 if (!gp) {
231 break;
Greg Daniel8199d942017-03-14 10:20:24 -0400232 }
233
Brian Salomon477d0ef2017-07-14 10:12:26 -0400234 std::unique_ptr<GrDrawOp> op =
Chris Daltonfebbffa2017-06-08 13:12:02 -0600235 BezierCubicTestOp::Make(std::move(gp), bounds, color);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400236 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000237 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000238 ++col;
239 if (numCols == col) {
240 col = 0;
241 ++row;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000242 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000243 }
244 }
245 }
246
247private:
248 typedef GM INHERITED;
249};
250
251//////////////////////////////////////////////////////////////////////////////
252
Brian Salomon477d0ef2017-07-14 10:12:26 -0400253class BezierConicTestOp : public BezierTestOp {
Chris Daltonfebbffa2017-06-08 13:12:02 -0600254public:
255 DEFINE_OP_CLASS_ID
256
257 const char* name() const override { return "BezierConicTestOp"; }
258
Brian Salomon477d0ef2017-07-14 10:12:26 -0400259 static std::unique_ptr<GrDrawOp> Make(sk_sp<GrGeometryProcessor> gp, const SkRect& rect,
260 GrColor color, const SkMatrix& klm) {
261 return std::unique_ptr<GrMeshDrawOp>(
262 new BezierConicTestOp(std::move(gp), rect, color, klm));
Chris Daltonfebbffa2017-06-08 13:12:02 -0600263 }
264
265private:
266 BezierConicTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
267 const SkMatrix& klm)
Brian Salomon477d0ef2017-07-14 10:12:26 -0400268 : INHERITED(std::move(gp), rect, color, ClassID()), fKLM(klm) {}
269
Chris Daltonfebbffa2017-06-08 13:12:02 -0600270 struct Vertex {
271 SkPoint fPosition;
272 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
273 };
274
Brian Salomon91326c32017-08-09 16:02:19 -0400275 void onPrepareDraws(Target* target) override {
Chris Daltonfebbffa2017-06-08 13:12:02 -0600276 QuadHelper helper;
Brian Salomon477d0ef2017-07-14 10:12:26 -0400277 size_t vertexStride = this->gp()->getVertexStride();
Chris Daltonfebbffa2017-06-08 13:12:02 -0600278 SkASSERT(vertexStride == sizeof(Vertex));
279 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
280 if (!verts) {
281 return;
282 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400283 SkRect rect = this->rect();
Cary Clark74f623d2017-11-06 20:02:02 -0500284 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect.fLeft, rect.fTop, rect.fRight,
285 rect.fBottom, sizeof(Vertex));
Chris Daltonfebbffa2017-06-08 13:12:02 -0600286 for (int v = 0; v < 4; ++v) {
Cary Clarke4442cb2017-10-18 11:46:18 -0400287 SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
288 fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600289 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400290 helper.recordDraw(target, this->gp(), this->makePipeline(target));
Chris Daltonfebbffa2017-06-08 13:12:02 -0600291 }
292
293 SkMatrix fKLM;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600294
295 static constexpr int kVertsPerCubic = 4;
296 static constexpr int kIndicesPerCubic = 6;
297
Brian Salomon477d0ef2017-07-14 10:12:26 -0400298 typedef BezierTestOp INHERITED;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600299};
300
301
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000302/**
303 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
304 */
305class BezierConicEffects : public GM {
306public:
307 BezierConicEffects() {
308 this->setBGColor(0xFFFFFFFF);
309 }
310
311protected:
mtklein36352bf2015-03-25 18:17:31 -0700312 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000313 return SkString("bezier_conic_effects");
314 }
315
mtklein36352bf2015-03-25 18:17:31 -0700316 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700317 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000318 }
319
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000320
mtklein36352bf2015-03-25 18:17:31 -0700321 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400322 GrRenderTargetContext* renderTargetContext =
323 canvas->internal_private_accessTopLayerRenderTargetContext();
324 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700325 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000326 return;
327 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000328
robertphillips175dd9b2016-04-28 14:32:04 -0700329 GrContext* context = canvas->getGrContext();
330 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800331 return;
332 }
333
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000334 struct Vertex {
335 SkPoint fPosition;
336 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
337 };
338
mtkleindbfd7ab2016-09-01 11:24:54 -0700339 constexpr int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000340 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000341
342 // Mult by 3 for each edge effect type
343 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
344 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400345 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
346 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000347 int row = 0;
348 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700349 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000350
351 for (int i = 0; i < kNumConics; ++i) {
352 SkPoint baseControlPts[] = {
353 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
354 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
355 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
356 };
357 SkScalar weight = rand.nextRangeF(0.f, 2.f);
Ethan Nicholas1706f842017-11-10 11:58:19 -0500358 for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700359 sk_sp<GrGeometryProcessor> gp;
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500360 GrClipEdgeType et = (GrClipEdgeType)edgeType;
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400361 gp = GrConicEffect::Make(color, SkMatrix::I(), et, *context->contextPriv().caps(),
362 SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800363 if (!gp) {
364 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000365 }
366
Mike Reeddf85c382017-02-14 10:59:19 -0500367 SkScalar x = col * w;
368 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000369 SkPoint controlPts[] = {
370 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
371 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
372 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
373 };
374 SkConic dst[4];
csmartdaltoncc261272017-03-23 13:38:45 -0600375 SkMatrix klm;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000376 int cnt = chop_conic(controlPts, dst, weight);
csmartdaltoncc261272017-03-23 13:38:45 -0600377 GrPathUtils::getConicKLM(controlPts, weight, &klm);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000378
379 SkPaint ctrlPtPaint;
380 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
381 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400382 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000383 }
384
385 SkPaint polyPaint;
386 polyPaint.setColor(0xffA0A0A0);
387 polyPaint.setStrokeWidth(0);
388 polyPaint.setStyle(SkPaint::kStroke_Style);
389 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
390
391 SkPaint choppedPtPaint;
392 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
393
394 for (int c = 0; c < cnt; ++c) {
395 SkPoint* pts = dst[c].fPts;
396 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400397 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000398 }
399
400 SkRect bounds;
401 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
402 //bounds.set(bPts, 2);
403 bounds.set(pts, 3);
404
405 SkPaint boundsPaint;
406 boundsPaint.setColor(0xff808080);
407 boundsPaint.setStrokeWidth(0);
408 boundsPaint.setStyle(SkPaint::kStroke_Style);
409 canvas->drawRect(bounds, boundsPaint);
410
Brian Salomon477d0ef2017-07-14 10:12:26 -0400411 std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(gp, bounds, color, klm);
412 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000413 }
414 ++col;
415 if (numCols == col) {
416 col = 0;
417 ++row;
418 }
419 }
420 }
421 }
422
423private:
424 // Uses the max curvature function for quads to estimate
425 // where to chop the conic. If the max curvature is not
426 // found along the curve segment it will return 1 and
427 // dst[0] is the original conic. If it returns 2 the dst[0]
428 // and dst[1] are the two new conics.
429 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
430 SkScalar t = SkFindQuadMaxCurvature(src);
431 if (t == 0) {
432 if (dst) {
433 dst[0].set(src, weight);
434 }
435 return 1;
436 } else {
437 if (dst) {
438 SkConic conic;
439 conic.set(src, weight);
caryclark414c4292016-09-26 11:03:54 -0700440 if (!conic.chopAt(t, dst)) {
441 dst[0].set(src, weight);
442 return 1;
443 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000444 }
445 return 2;
446 }
447 }
448
449 // Calls split_conic on the entire conic and then once more on each subsection.
450 // Most cases will result in either 1 conic (chop point is not within t range)
451 // or 3 points (split once and then one subsection is split again).
452 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
453 SkConic dstTemp[2];
454 int conicCnt = split_conic(src, dstTemp, weight);
455 if (2 == conicCnt) {
456 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
457 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
458 } else {
459 dst[0] = dstTemp[0];
460 }
461 return conicCnt;
462 }
463
464 typedef GM INHERITED;
465};
466
467//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800468
Brian Salomon477d0ef2017-07-14 10:12:26 -0400469class BezierQuadTestOp : public BezierTestOp {
joshualitt95964c62015-02-11 13:45:50 -0800470public:
Brian Salomon25a88092016-12-01 09:36:50 -0500471 DEFINE_OP_CLASS_ID
Brian Salomon6b316e92016-12-16 09:35:49 -0500472 const char* name() const override { return "BezierQuadTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -0800473
Brian Salomon477d0ef2017-07-14 10:12:26 -0400474 static std::unique_ptr<GrDrawOp> Make(sk_sp<GrGeometryProcessor> gp, const SkRect& rect,
475 GrColor color, const GrPathUtils::QuadUVMatrix& devToUV) {
476 return std::unique_ptr<GrDrawOp>(new BezierQuadTestOp(std::move(gp), rect, color, devToUV));
joshualitt95964c62015-02-11 13:45:50 -0800477 }
478
479private:
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500480 BezierQuadTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
Brian Salomon6b316e92016-12-16 09:35:49 -0500481 const GrPathUtils::QuadUVMatrix& devToUV)
Brian Salomon477d0ef2017-07-14 10:12:26 -0400482 : INHERITED(std::move(gp), rect, color, ClassID()), fDevToUV(devToUV) {}
joshualitt95964c62015-02-11 13:45:50 -0800483
484 struct Vertex {
485 SkPoint fPosition;
486 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
487 };
488
Brian Salomon91326c32017-08-09 16:02:19 -0400489 void onPrepareDraws(Target* target) override {
bsalomonb5238a72015-05-05 07:49:49 -0700490 QuadHelper helper;
Brian Salomon477d0ef2017-07-14 10:12:26 -0400491 size_t vertexStride = this->gp()->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -0700492 SkASSERT(vertexStride == sizeof(Vertex));
bsalomon75398562015-08-17 12:55:38 -0700493 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
bsalomonb5238a72015-05-05 07:49:49 -0700494 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800495 return;
496 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400497 SkRect rect = this->rect();
Brian Salomonec42e152018-05-18 12:52:22 -0400498 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
joshualitt95964c62015-02-11 13:45:50 -0800499 fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400500 helper.recordDraw(target, this->gp(), this->makePipeline(target));
joshualitt95964c62015-02-11 13:45:50 -0800501 }
502
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500503 GrPathUtils::QuadUVMatrix fDevToUV;
joshualitt95964c62015-02-11 13:45:50 -0800504
mtkleindbfd7ab2016-09-01 11:24:54 -0700505 static constexpr int kVertsPerCubic = 4;
506 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800507
Brian Salomon477d0ef2017-07-14 10:12:26 -0400508 typedef BezierTestOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800509};
510
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000511/**
512 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
513 */
514class BezierQuadEffects : public GM {
515public:
516 BezierQuadEffects() {
517 this->setBGColor(0xFFFFFFFF);
518 }
519
520protected:
mtklein36352bf2015-03-25 18:17:31 -0700521 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000522 return SkString("bezier_quad_effects");
523 }
524
mtklein36352bf2015-03-25 18:17:31 -0700525 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700526 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000527 }
528
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000529
mtklein36352bf2015-03-25 18:17:31 -0700530 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400531 GrRenderTargetContext* renderTargetContext =
532 canvas->internal_private_accessTopLayerRenderTargetContext();
533 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700534 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000535 return;
536 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000537
robertphillips175dd9b2016-04-28 14:32:04 -0700538 GrContext* context = canvas->getGrContext();
539 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800540 return;
541 }
542
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000543 struct Vertex {
544 SkPoint fPosition;
545 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
546 };
547
mtkleindbfd7ab2016-09-01 11:24:54 -0700548 constexpr int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000549 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000550
551 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
552 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400553 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
554 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000555 int row = 0;
556 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700557 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000558
559 for (int i = 0; i < kNumQuads; ++i) {
560 SkPoint baseControlPts[] = {
561 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
562 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
563 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
564 };
Ethan Nicholas1706f842017-11-10 11:58:19 -0500565 for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700566 sk_sp<GrGeometryProcessor> gp;
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500567 GrClipEdgeType et = (GrClipEdgeType)edgeType;
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400568 gp = GrQuadEffect::Make(color, SkMatrix::I(), et, *context->contextPriv().caps(),
569 SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800570 if (!gp) {
571 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000572 }
573
Mike Reeddf85c382017-02-14 10:59:19 -0500574 SkScalar x = col * w;
575 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000576 SkPoint controlPts[] = {
577 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
578 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
579 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
580 };
581 SkPoint chopped[5];
582 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
583
584 SkPaint ctrlPtPaint;
585 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
586 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400587 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000588 }
589
590 SkPaint polyPaint;
591 polyPaint.setColor(0xffA0A0A0);
592 polyPaint.setStrokeWidth(0);
593 polyPaint.setStyle(SkPaint::kStroke_Style);
594 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
595
596 SkPaint choppedPtPaint;
597 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
598
599 for (int c = 0; c < cnt; ++c) {
600 SkPoint* pts = chopped + 2 * c;
601
602 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400603 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000604 }
605
606 SkRect bounds;
607 bounds.set(pts, 3);
608
609 SkPaint boundsPaint;
610 boundsPaint.setColor(0xff808080);
611 boundsPaint.setStrokeWidth(0);
612 boundsPaint.setStyle(SkPaint::kStroke_Style);
613 canvas->drawRect(bounds, boundsPaint);
614
robertphillips28a838e2016-06-23 14:07:00 -0700615 GrPaint grPaint;
Brian Salomona1633922017-01-09 11:46:10 -0500616 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
joshualitt3f284d72015-02-11 11:34:58 -0800617
joshualitt95964c62015-02-11 13:45:50 -0800618 GrPathUtils::QuadUVMatrix DevToUV(pts);
619
Brian Salomon477d0ef2017-07-14 10:12:26 -0400620 std::unique_ptr<GrDrawOp> op =
Brian Salomonf8334782017-01-03 09:42:58 -0500621 BezierQuadTestOp::Make(gp, bounds, color, DevToUV);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400622 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000623 }
624 ++col;
625 if (numCols == col) {
626 col = 0;
627 ++row;
628 }
629 }
630 }
631 }
632
633private:
634 typedef GM INHERITED;
635};
636
halcanary385fe4d2015-08-26 13:07:48 -0700637DEF_GM(return new BezierCubicEffects;)
638DEF_GM(return new BezierConicEffects;)
639DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000640}
641
642#endif