blob: 1266e8d87c675c3baadef509b2fb87c05c9b8148 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "gm/gm.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040011#include "include/core/SkBlendMode.h"
12#include "include/core/SkCanvas.h"
13#include "include/core/SkMatrix.h"
14#include "include/core/SkPaint.h"
15#include "include/core/SkPoint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050016#include "include/core/SkPoint3.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040017#include "include/core/SkRect.h"
18#include "include/core/SkRefCnt.h"
19#include "include/core/SkScalar.h"
20#include "include/core/SkSize.h"
21#include "include/core/SkString.h"
22#include "include/core/SkTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "include/gpu/GrContext.h"
24#include "include/private/GrRecordingContext.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040025#include "include/private/GrSharedEnums.h"
26#include "include/private/GrTypesPriv.h"
27#include "include/private/SkColorData.h"
28#include "include/utils/SkRandom.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050029#include "src/core/SkGeometry.h"
30#include "src/core/SkPointPriv.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040031#include "src/gpu/GrCaps.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050032#include "src/gpu/GrContextPriv.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040033#include "src/gpu/GrGeometryProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050034#include "src/gpu/GrMemoryPool.h"
35#include "src/gpu/GrOpFlushState.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040036#include "src/gpu/GrPaint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050037#include "src/gpu/GrPathUtils.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040038#include "src/gpu/GrProcessorAnalysis.h"
39#include "src/gpu/GrProcessorSet.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050040#include "src/gpu/GrRecordingContextPriv.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040041#include "src/gpu/GrRenderTargetContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050042#include "src/gpu/GrRenderTargetContextPriv.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040043#include "src/gpu/GrUserStencilSettings.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050044#include "src/gpu/effects/GrBezierEffect.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040045#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
46#include "src/gpu/ops/GrDrawOp.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050047#include "src/gpu/ops/GrMeshDrawOp.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040048#include "src/gpu/ops/GrOp.h"
49
50#include <memory>
51#include <utility>
52
53class GrAppliedClip;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000054
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000055namespace skiagm {
joshualitt95964c62015-02-11 13:45:50 -080056
Brian Salomon477d0ef2017-07-14 10:12:26 -040057class BezierTestOp : public GrMeshDrawOp {
58public:
59 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
60
Brian Osman5ced0bf2019-03-15 10:15:29 -040061 GrProcessorSet::Analysis finalize(const GrCaps& caps, const GrAppliedClip* clip,
62 GrFSAAType fsaaType, GrClampType clampType) override {
Chris Daltonb8fff0d2019-03-05 10:11:58 -070063 return fProcessorSet.finalize(
64 fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
Brian Osman5ced0bf2019-03-15 10:15:29 -040065 &GrUserStencilSettings::kUnused, fsaaType, caps, clampType, &fColor);
Brian Salomon477d0ef2017-07-14 10:12:26 -040066 }
67
Chris Dalton1706cbf2019-05-21 19:35:29 -060068 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -040069 fProcessorSet.visitProxies(func);
70 }
71
Brian Salomon477d0ef2017-07-14 10:12:26 -040072protected:
Brian Osmancf860852018-10-31 14:04:39 -040073 BezierTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, const SkPMColor4f& color,
Brian Salomon7eae3e02018-08-07 14:02:38 +000074 int32_t classID)
Brian Salomon477d0ef2017-07-14 10:12:26 -040075 : INHERITED(classID)
76 , fRect(rect)
77 , fColor(color)
78 , fGeometryProcessor(std::move(gp))
79 , fProcessorSet(SkBlendMode::kSrc) {
80 this->setBounds(rect, HasAABloat::kYes, IsZeroArea::kNo);
81 }
82
Chris Dalton07cdcfc92019-02-26 11:13:22 -070083 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
84 flushState->executeDrawsAndUploadsForMeshDrawOp(
85 this, chainBounds, std::move(fProcessorSet));
Brian Salomon477d0ef2017-07-14 10:12:26 -040086 }
87
Brian Salomon7eae3e02018-08-07 14:02:38 +000088 sk_sp<const GrGeometryProcessor> gp() const { return fGeometryProcessor; }
Brian Salomon477d0ef2017-07-14 10:12:26 -040089
90 const SkRect& rect() const { return fRect; }
Brian Osmancf860852018-10-31 14:04:39 -040091 const SkPMColor4f& color() const { return fColor; }
Brian Salomon477d0ef2017-07-14 10:12:26 -040092
93private:
Brian Salomon477d0ef2017-07-14 10:12:26 -040094 SkRect fRect;
Brian Osmancf860852018-10-31 14:04:39 -040095 SkPMColor4f fColor;
Brian Salomon7eae3e02018-08-07 14:02:38 +000096 sk_sp<const GrGeometryProcessor> fGeometryProcessor;
Brian Salomon477d0ef2017-07-14 10:12:26 -040097 GrProcessorSet fProcessorSet;
98
99 typedef GrMeshDrawOp INHERITED;
100};
101
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000102/**
103 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
104 */
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000105
Brian Salomon477d0ef2017-07-14 10:12:26 -0400106class BezierConicTestOp : public BezierTestOp {
Chris Daltonfebbffa2017-06-08 13:12:02 -0600107public:
108 DEFINE_OP_CLASS_ID
109
110 const char* name() const override { return "BezierConicTestOp"; }
111
Robert Phillipsbe9aff22019-02-15 11:33:22 -0500112 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Brian Salomon7eae3e02018-08-07 14:02:38 +0000113 sk_sp<const GrGeometryProcessor> gp,
Robert Phillips7c525e62018-06-12 10:11:12 -0400114 const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400115 const SkPMColor4f& color,
Robert Phillips7c525e62018-06-12 10:11:12 -0400116 const SkMatrix& klm) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500117 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400118
119 return pool->allocate<BezierConicTestOp>(std::move(gp), rect, color, klm);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600120 }
121
122private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400123 friend class ::GrOpMemoryPool; // for ctor
124
Brian Osman936fe7d2018-10-30 15:30:35 -0400125 BezierConicTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400126 const SkPMColor4f& color, const SkMatrix& klm)
Brian Salomon477d0ef2017-07-14 10:12:26 -0400127 : INHERITED(std::move(gp), rect, color, ClassID()), fKLM(klm) {}
128
Chris Daltonfebbffa2017-06-08 13:12:02 -0600129 struct Vertex {
130 SkPoint fPosition;
131 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
132 };
133
Brian Salomon91326c32017-08-09 16:02:19 -0400134 void onPrepareDraws(Target* target) override {
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500135 SkASSERT(this->gp()->vertexStride() == sizeof(Vertex));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000136 QuadHelper helper(target, sizeof(Vertex), 1);
137 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600138 if (!verts) {
139 return;
140 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400141 SkRect rect = this->rect();
Cary Clark74f623d2017-11-06 20:02:02 -0500142 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect.fLeft, rect.fTop, rect.fRight,
143 rect.fBottom, sizeof(Vertex));
Chris Daltonfebbffa2017-06-08 13:12:02 -0600144 for (int v = 0; v < 4; ++v) {
Cary Clarke4442cb2017-10-18 11:46:18 -0400145 SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
146 fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600147 }
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700148
149 helper.recordDraw(target, this->gp());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600150 }
151
152 SkMatrix fKLM;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600153
154 static constexpr int kVertsPerCubic = 4;
155 static constexpr int kIndicesPerCubic = 6;
156
Brian Salomon477d0ef2017-07-14 10:12:26 -0400157 typedef BezierTestOp INHERITED;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600158};
159
160
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000161/**
162 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
163 */
Chris Dalton3a778372019-02-07 15:23:36 -0700164class BezierConicEffects : public GpuGM {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000165public:
166 BezierConicEffects() {
167 this->setBGColor(0xFFFFFFFF);
168 }
169
170protected:
mtklein36352bf2015-03-25 18:17:31 -0700171 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000172 return SkString("bezier_conic_effects");
173 }
174
mtklein36352bf2015-03-25 18:17:31 -0700175 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700176 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000177 }
178
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000179
Chris Dalton3a778372019-02-07 15:23:36 -0700180 void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
181 SkCanvas* canvas) override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000182 struct Vertex {
183 SkPoint fPosition;
184 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
185 };
186
mtkleindbfd7ab2016-09-01 11:24:54 -0700187 constexpr int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000188 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000189
190 // Mult by 3 for each edge effect type
191 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
192 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400193 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
194 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000195 int row = 0;
196 int col = 0;
Brian Osmancf860852018-10-31 14:04:39 -0400197 SkPMColor4f color = SkPMColor4f::FromBytes_RGBA(0xff000000);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000198
199 for (int i = 0; i < kNumConics; ++i) {
200 SkPoint baseControlPts[] = {
201 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
202 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
203 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
204 };
205 SkScalar weight = rand.nextRangeF(0.f, 2.f);
Ethan Nicholas1706f842017-11-10 11:58:19 -0500206 for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700207 sk_sp<GrGeometryProcessor> gp;
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500208 GrClipEdgeType et = (GrClipEdgeType)edgeType;
Robert Phillips9da87e02019-02-04 13:26:26 -0500209 gp = GrConicEffect::Make(color, SkMatrix::I(), et, *context->priv().caps(),
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400210 SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800211 if (!gp) {
212 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000213 }
214
Mike Reeddf85c382017-02-14 10:59:19 -0500215 SkScalar x = col * w;
216 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000217 SkPoint controlPts[] = {
218 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
219 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
220 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
221 };
222 SkConic dst[4];
csmartdaltoncc261272017-03-23 13:38:45 -0600223 SkMatrix klm;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000224 int cnt = chop_conic(controlPts, dst, weight);
csmartdaltoncc261272017-03-23 13:38:45 -0600225 GrPathUtils::getConicKLM(controlPts, weight, &klm);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000226
227 SkPaint ctrlPtPaint;
228 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
229 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400230 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000231 }
232
233 SkPaint polyPaint;
234 polyPaint.setColor(0xffA0A0A0);
235 polyPaint.setStrokeWidth(0);
236 polyPaint.setStyle(SkPaint::kStroke_Style);
237 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
238
239 SkPaint choppedPtPaint;
240 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
241
242 for (int c = 0; c < cnt; ++c) {
243 SkPoint* pts = dst[c].fPts;
244 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400245 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000246 }
247
248 SkRect bounds;
249 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
250 //bounds.set(bPts, 2);
251 bounds.set(pts, 3);
252
253 SkPaint boundsPaint;
254 boundsPaint.setColor(0xff808080);
255 boundsPaint.setStrokeWidth(0);
256 boundsPaint.setStyle(SkPaint::kStroke_Style);
257 canvas->drawRect(bounds, boundsPaint);
258
Robert Phillips7c525e62018-06-12 10:11:12 -0400259 std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(context, gp, bounds,
260 color, klm);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400261 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000262 }
263 ++col;
264 if (numCols == col) {
265 col = 0;
266 ++row;
267 }
268 }
269 }
270 }
271
272private:
273 // Uses the max curvature function for quads to estimate
274 // where to chop the conic. If the max curvature is not
275 // found along the curve segment it will return 1 and
276 // dst[0] is the original conic. If it returns 2 the dst[0]
277 // and dst[1] are the two new conics.
278 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
279 SkScalar t = SkFindQuadMaxCurvature(src);
Chris Dalton1d474dd2018-07-24 01:08:31 -0600280 if (t == 0 || t == 1) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000281 if (dst) {
282 dst[0].set(src, weight);
283 }
284 return 1;
285 } else {
286 if (dst) {
287 SkConic conic;
288 conic.set(src, weight);
caryclark414c4292016-09-26 11:03:54 -0700289 if (!conic.chopAt(t, dst)) {
290 dst[0].set(src, weight);
291 return 1;
292 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000293 }
294 return 2;
295 }
296 }
297
298 // Calls split_conic on the entire conic and then once more on each subsection.
299 // Most cases will result in either 1 conic (chop point is not within t range)
300 // or 3 points (split once and then one subsection is split again).
301 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
302 SkConic dstTemp[2];
303 int conicCnt = split_conic(src, dstTemp, weight);
304 if (2 == conicCnt) {
305 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
306 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
307 } else {
308 dst[0] = dstTemp[0];
309 }
310 return conicCnt;
311 }
312
313 typedef GM INHERITED;
314};
315
316//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800317
Brian Salomon477d0ef2017-07-14 10:12:26 -0400318class BezierQuadTestOp : public BezierTestOp {
joshualitt95964c62015-02-11 13:45:50 -0800319public:
Brian Salomon25a88092016-12-01 09:36:50 -0500320 DEFINE_OP_CLASS_ID
Brian Salomon6b316e92016-12-16 09:35:49 -0500321 const char* name() const override { return "BezierQuadTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -0800322
Robert Phillips7c525e62018-06-12 10:11:12 -0400323 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
Brian Salomon7eae3e02018-08-07 14:02:38 +0000324 sk_sp<const GrGeometryProcessor> gp,
Robert Phillips7c525e62018-06-12 10:11:12 -0400325 const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400326 const SkPMColor4f& color,
Robert Phillips7c525e62018-06-12 10:11:12 -0400327 const GrPathUtils::QuadUVMatrix& devToUV) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500328 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400329
330 return pool->allocate<BezierQuadTestOp>(std::move(gp), rect, color, devToUV);
joshualitt95964c62015-02-11 13:45:50 -0800331 }
332
333private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400334 friend class ::GrOpMemoryPool; // for ctor
335
Brian Osman936fe7d2018-10-30 15:30:35 -0400336 BezierQuadTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400337 const SkPMColor4f& color, const GrPathUtils::QuadUVMatrix& devToUV)
Brian Salomon477d0ef2017-07-14 10:12:26 -0400338 : INHERITED(std::move(gp), rect, color, ClassID()), fDevToUV(devToUV) {}
joshualitt95964c62015-02-11 13:45:50 -0800339
340 struct Vertex {
341 SkPoint fPosition;
342 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
343 };
344
Brian Salomon91326c32017-08-09 16:02:19 -0400345 void onPrepareDraws(Target* target) override {
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500346 SkASSERT(this->gp()->vertexStride() == sizeof(Vertex));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000347 QuadHelper helper(target, sizeof(Vertex), 1);
348 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
bsalomonb5238a72015-05-05 07:49:49 -0700349 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800350 return;
351 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400352 SkRect rect = this->rect();
Brian Salomonec42e152018-05-18 12:52:22 -0400353 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
Brian Osman568bec72018-12-26 16:48:25 -0500354 fDevToUV.apply(verts, 4, sizeof(Vertex), sizeof(SkPoint));
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700355 helper.recordDraw(target, this->gp());
joshualitt95964c62015-02-11 13:45:50 -0800356 }
357
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500358 GrPathUtils::QuadUVMatrix fDevToUV;
joshualitt95964c62015-02-11 13:45:50 -0800359
mtkleindbfd7ab2016-09-01 11:24:54 -0700360 static constexpr int kVertsPerCubic = 4;
361 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800362
Brian Salomon477d0ef2017-07-14 10:12:26 -0400363 typedef BezierTestOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800364};
365
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000366/**
367 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
368 */
Chris Dalton3a778372019-02-07 15:23:36 -0700369class BezierQuadEffects : public GpuGM {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000370public:
371 BezierQuadEffects() {
372 this->setBGColor(0xFFFFFFFF);
373 }
374
375protected:
mtklein36352bf2015-03-25 18:17:31 -0700376 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000377 return SkString("bezier_quad_effects");
378 }
379
mtklein36352bf2015-03-25 18:17:31 -0700380 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700381 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000382 }
383
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000384
Chris Dalton3a778372019-02-07 15:23:36 -0700385 void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
386 SkCanvas* canvas) override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000387 struct Vertex {
388 SkPoint fPosition;
389 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
390 };
391
mtkleindbfd7ab2016-09-01 11:24:54 -0700392 constexpr int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000393 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000394
395 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
396 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400397 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
398 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000399 int row = 0;
400 int col = 0;
Brian Osmancf860852018-10-31 14:04:39 -0400401 SkPMColor4f color = SkPMColor4f::FromBytes_RGBA(0xff000000);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000402
403 for (int i = 0; i < kNumQuads; ++i) {
404 SkPoint baseControlPts[] = {
405 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
406 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
407 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
408 };
Ethan Nicholas1706f842017-11-10 11:58:19 -0500409 for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700410 sk_sp<GrGeometryProcessor> gp;
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500411 GrClipEdgeType et = (GrClipEdgeType)edgeType;
Robert Phillips9da87e02019-02-04 13:26:26 -0500412 gp = GrQuadEffect::Make(color, SkMatrix::I(), et, *context->priv().caps(),
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400413 SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800414 if (!gp) {
415 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000416 }
417
Mike Reeddf85c382017-02-14 10:59:19 -0500418 SkScalar x = col * w;
419 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000420 SkPoint controlPts[] = {
421 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
422 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
423 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
424 };
425 SkPoint chopped[5];
426 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
427
428 SkPaint ctrlPtPaint;
429 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
430 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400431 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000432 }
433
434 SkPaint polyPaint;
435 polyPaint.setColor(0xffA0A0A0);
436 polyPaint.setStrokeWidth(0);
437 polyPaint.setStyle(SkPaint::kStroke_Style);
438 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
439
440 SkPaint choppedPtPaint;
441 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
442
443 for (int c = 0; c < cnt; ++c) {
444 SkPoint* pts = chopped + 2 * c;
445
446 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400447 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000448 }
449
450 SkRect bounds;
451 bounds.set(pts, 3);
452
453 SkPaint boundsPaint;
454 boundsPaint.setColor(0xff808080);
455 boundsPaint.setStrokeWidth(0);
456 boundsPaint.setStyle(SkPaint::kStroke_Style);
457 canvas->drawRect(bounds, boundsPaint);
458
robertphillips28a838e2016-06-23 14:07:00 -0700459 GrPaint grPaint;
Brian Salomona1633922017-01-09 11:46:10 -0500460 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
joshualitt3f284d72015-02-11 11:34:58 -0800461
joshualitt95964c62015-02-11 13:45:50 -0800462 GrPathUtils::QuadUVMatrix DevToUV(pts);
463
Robert Phillips7c525e62018-06-12 10:11:12 -0400464 std::unique_ptr<GrDrawOp> op = BezierQuadTestOp::Make(context, gp,
465 bounds, color, DevToUV);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400466 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000467 }
468 ++col;
469 if (numCols == col) {
470 col = 0;
471 ++row;
472 }
473 }
474 }
475 }
476
477private:
478 typedef GM INHERITED;
479};
480
halcanary385fe4d2015-08-26 13:07:48 -0700481DEF_GM(return new BezierConicEffects;)
482DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000483}