blob: 70bcf77f9ee0f4aceaa99107a0831fde12ec194a [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"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040037#include "src/gpu/GrProcessorAnalysis.h"
38#include "src/gpu/GrProcessorSet.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050039#include "src/gpu/GrRecordingContextPriv.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040040#include "src/gpu/GrRenderTargetContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050041#include "src/gpu/GrRenderTargetContextPriv.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040042#include "src/gpu/GrUserStencilSettings.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050043#include "src/gpu/effects/GrBezierEffect.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040044#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
Michael Ludwig663afe52019-06-03 16:46:19 -040045#include "src/gpu/geometry/GrPathUtils.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040046#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
Chris Dalton6ce447a2019-06-23 18:07:38 -060061 GrProcessorSet::Analysis finalize(
62 const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
63 GrClampType clampType) override {
Chris Daltonb8fff0d2019-03-05 10:11:58 -070064 return fProcessorSet.finalize(
65 fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
Chris Dalton6ce447a2019-06-23 18:07:38 -060066 &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, caps, clampType, &fColor);
Brian Salomon477d0ef2017-07-14 10:12:26 -040067 }
68
Chris Dalton1706cbf2019-05-21 19:35:29 -060069 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -040070 fProcessorSet.visitProxies(func);
71 }
72
Brian Salomon477d0ef2017-07-14 10:12:26 -040073protected:
Brian Osmancf860852018-10-31 14:04:39 -040074 BezierTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, const SkPMColor4f& color,
Brian Salomon7eae3e02018-08-07 14:02:38 +000075 int32_t classID)
Brian Salomon477d0ef2017-07-14 10:12:26 -040076 : INHERITED(classID)
77 , fRect(rect)
78 , fColor(color)
79 , fGeometryProcessor(std::move(gp))
80 , fProcessorSet(SkBlendMode::kSrc) {
Greg Daniel5faf4742019-10-01 15:14:44 -040081 this->setBounds(rect, HasAABloat::kYes, IsHairline::kNo);
Brian Salomon477d0ef2017-07-14 10:12:26 -040082 }
83
Chris Dalton07cdcfc92019-02-26 11:13:22 -070084 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) override {
85 flushState->executeDrawsAndUploadsForMeshDrawOp(
86 this, chainBounds, std::move(fProcessorSet));
Brian Salomon477d0ef2017-07-14 10:12:26 -040087 }
88
Brian Salomon7eae3e02018-08-07 14:02:38 +000089 sk_sp<const GrGeometryProcessor> gp() const { return fGeometryProcessor; }
Brian Salomon477d0ef2017-07-14 10:12:26 -040090
91 const SkRect& rect() const { return fRect; }
Brian Osmancf860852018-10-31 14:04:39 -040092 const SkPMColor4f& color() const { return fColor; }
Brian Salomon477d0ef2017-07-14 10:12:26 -040093
94private:
Brian Salomon477d0ef2017-07-14 10:12:26 -040095 SkRect fRect;
Brian Osmancf860852018-10-31 14:04:39 -040096 SkPMColor4f fColor;
Brian Salomon7eae3e02018-08-07 14:02:38 +000097 sk_sp<const GrGeometryProcessor> fGeometryProcessor;
Brian Salomon477d0ef2017-07-14 10:12:26 -040098 GrProcessorSet fProcessorSet;
99
100 typedef GrMeshDrawOp INHERITED;
101};
102
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000103/**
104 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
105 */
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000106
Brian Salomon477d0ef2017-07-14 10:12:26 -0400107class BezierConicTestOp : public BezierTestOp {
Chris Daltonfebbffa2017-06-08 13:12:02 -0600108public:
109 DEFINE_OP_CLASS_ID
110
111 const char* name() const override { return "BezierConicTestOp"; }
112
Robert Phillipsbe9aff22019-02-15 11:33:22 -0500113 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Brian Salomon7eae3e02018-08-07 14:02:38 +0000114 sk_sp<const GrGeometryProcessor> gp,
Robert Phillips7c525e62018-06-12 10:11:12 -0400115 const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400116 const SkPMColor4f& color,
Robert Phillips7c525e62018-06-12 10:11:12 -0400117 const SkMatrix& klm) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500118 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400119
120 return pool->allocate<BezierConicTestOp>(std::move(gp), rect, color, klm);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600121 }
122
123private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400124 friend class ::GrOpMemoryPool; // for ctor
125
Brian Osman936fe7d2018-10-30 15:30:35 -0400126 BezierConicTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400127 const SkPMColor4f& color, const SkMatrix& klm)
Brian Salomon477d0ef2017-07-14 10:12:26 -0400128 : INHERITED(std::move(gp), rect, color, ClassID()), fKLM(klm) {}
129
Chris Daltonfebbffa2017-06-08 13:12:02 -0600130 struct Vertex {
131 SkPoint fPosition;
132 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
133 };
134
Brian Salomon91326c32017-08-09 16:02:19 -0400135 void onPrepareDraws(Target* target) override {
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500136 SkASSERT(this->gp()->vertexStride() == sizeof(Vertex));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000137 QuadHelper helper(target, sizeof(Vertex), 1);
138 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600139 if (!verts) {
140 return;
141 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400142 SkRect rect = this->rect();
Cary Clark74f623d2017-11-06 20:02:02 -0500143 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect.fLeft, rect.fTop, rect.fRight,
144 rect.fBottom, sizeof(Vertex));
Chris Daltonfebbffa2017-06-08 13:12:02 -0600145 for (int v = 0; v < 4; ++v) {
Cary Clarke4442cb2017-10-18 11:46:18 -0400146 SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
147 fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600148 }
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700149
150 helper.recordDraw(target, this->gp());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600151 }
152
153 SkMatrix fKLM;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600154
155 static constexpr int kVertsPerCubic = 4;
156 static constexpr int kIndicesPerCubic = 6;
157
Brian Salomon477d0ef2017-07-14 10:12:26 -0400158 typedef BezierTestOp INHERITED;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600159};
160
161
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000162/**
163 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
164 */
Chris Dalton3a778372019-02-07 15:23:36 -0700165class BezierConicEffects : public GpuGM {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000166public:
167 BezierConicEffects() {
168 this->setBGColor(0xFFFFFFFF);
169 }
170
171protected:
mtklein36352bf2015-03-25 18:17:31 -0700172 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000173 return SkString("bezier_conic_effects");
174 }
175
mtklein36352bf2015-03-25 18:17:31 -0700176 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700177 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000178 }
179
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000180
Chris Dalton3a778372019-02-07 15:23:36 -0700181 void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
182 SkCanvas* canvas) override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000183 struct Vertex {
184 SkPoint fPosition;
185 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
186 };
187
mtkleindbfd7ab2016-09-01 11:24:54 -0700188 constexpr int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000189 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000190
191 // Mult by 3 for each edge effect type
192 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
193 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400194 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
195 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000196 int row = 0;
197 int col = 0;
Brian Osmancf860852018-10-31 14:04:39 -0400198 SkPMColor4f color = SkPMColor4f::FromBytes_RGBA(0xff000000);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000199
200 for (int i = 0; i < kNumConics; ++i) {
201 SkPoint baseControlPts[] = {
202 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
203 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
204 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
205 };
206 SkScalar weight = rand.nextRangeF(0.f, 2.f);
Ethan Nicholas1706f842017-11-10 11:58:19 -0500207 for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700208 sk_sp<GrGeometryProcessor> gp;
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500209 GrClipEdgeType et = (GrClipEdgeType)edgeType;
Robert Phillips9da87e02019-02-04 13:26:26 -0500210 gp = GrConicEffect::Make(color, SkMatrix::I(), et, *context->priv().caps(),
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400211 SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800212 if (!gp) {
213 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000214 }
215
Mike Reeddf85c382017-02-14 10:59:19 -0500216 SkScalar x = col * w;
217 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000218 SkPoint controlPts[] = {
219 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
220 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
221 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
222 };
223 SkConic dst[4];
csmartdaltoncc261272017-03-23 13:38:45 -0600224 SkMatrix klm;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000225 int cnt = chop_conic(controlPts, dst, weight);
csmartdaltoncc261272017-03-23 13:38:45 -0600226 GrPathUtils::getConicKLM(controlPts, weight, &klm);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000227
228 SkPaint ctrlPtPaint;
229 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
230 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400231 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000232 }
233
234 SkPaint polyPaint;
235 polyPaint.setColor(0xffA0A0A0);
236 polyPaint.setStrokeWidth(0);
237 polyPaint.setStyle(SkPaint::kStroke_Style);
238 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
239
240 SkPaint choppedPtPaint;
241 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
242
243 for (int c = 0; c < cnt; ++c) {
244 SkPoint* pts = dst[c].fPts;
245 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400246 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000247 }
248
249 SkRect bounds;
250 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
251 //bounds.set(bPts, 2);
Mike Reed92b33352019-08-24 19:39:13 -0400252 bounds.setBounds(pts, 3);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000253
254 SkPaint boundsPaint;
255 boundsPaint.setColor(0xff808080);
256 boundsPaint.setStrokeWidth(0);
257 boundsPaint.setStyle(SkPaint::kStroke_Style);
258 canvas->drawRect(bounds, boundsPaint);
259
Robert Phillips7c525e62018-06-12 10:11:12 -0400260 std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(context, gp, bounds,
261 color, klm);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400262 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000263 }
264 ++col;
265 if (numCols == col) {
266 col = 0;
267 ++row;
268 }
269 }
270 }
271 }
272
273private:
274 // Uses the max curvature function for quads to estimate
275 // where to chop the conic. If the max curvature is not
276 // found along the curve segment it will return 1 and
277 // dst[0] is the original conic. If it returns 2 the dst[0]
278 // and dst[1] are the two new conics.
279 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
280 SkScalar t = SkFindQuadMaxCurvature(src);
Chris Dalton1d474dd2018-07-24 01:08:31 -0600281 if (t == 0 || t == 1) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000282 if (dst) {
283 dst[0].set(src, weight);
284 }
285 return 1;
286 } else {
287 if (dst) {
288 SkConic conic;
289 conic.set(src, weight);
caryclark414c4292016-09-26 11:03:54 -0700290 if (!conic.chopAt(t, dst)) {
291 dst[0].set(src, weight);
292 return 1;
293 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000294 }
295 return 2;
296 }
297 }
298
299 // Calls split_conic on the entire conic and then once more on each subsection.
300 // Most cases will result in either 1 conic (chop point is not within t range)
301 // or 3 points (split once and then one subsection is split again).
302 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
303 SkConic dstTemp[2];
304 int conicCnt = split_conic(src, dstTemp, weight);
305 if (2 == conicCnt) {
306 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
307 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
308 } else {
309 dst[0] = dstTemp[0];
310 }
311 return conicCnt;
312 }
313
314 typedef GM INHERITED;
315};
316
317//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800318
Brian Salomon477d0ef2017-07-14 10:12:26 -0400319class BezierQuadTestOp : public BezierTestOp {
joshualitt95964c62015-02-11 13:45:50 -0800320public:
Brian Salomon25a88092016-12-01 09:36:50 -0500321 DEFINE_OP_CLASS_ID
Brian Salomon6b316e92016-12-16 09:35:49 -0500322 const char* name() const override { return "BezierQuadTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -0800323
Robert Phillips7c525e62018-06-12 10:11:12 -0400324 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
Brian Salomon7eae3e02018-08-07 14:02:38 +0000325 sk_sp<const GrGeometryProcessor> gp,
Robert Phillips7c525e62018-06-12 10:11:12 -0400326 const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400327 const SkPMColor4f& color,
Robert Phillips7c525e62018-06-12 10:11:12 -0400328 const GrPathUtils::QuadUVMatrix& devToUV) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500329 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400330
331 return pool->allocate<BezierQuadTestOp>(std::move(gp), rect, color, devToUV);
joshualitt95964c62015-02-11 13:45:50 -0800332 }
333
334private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400335 friend class ::GrOpMemoryPool; // for ctor
336
Brian Osman936fe7d2018-10-30 15:30:35 -0400337 BezierQuadTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400338 const SkPMColor4f& color, const GrPathUtils::QuadUVMatrix& devToUV)
Brian Salomon477d0ef2017-07-14 10:12:26 -0400339 : INHERITED(std::move(gp), rect, color, ClassID()), fDevToUV(devToUV) {}
joshualitt95964c62015-02-11 13:45:50 -0800340
341 struct Vertex {
342 SkPoint fPosition;
343 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
344 };
345
Brian Salomon91326c32017-08-09 16:02:19 -0400346 void onPrepareDraws(Target* target) override {
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500347 SkASSERT(this->gp()->vertexStride() == sizeof(Vertex));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000348 QuadHelper helper(target, sizeof(Vertex), 1);
349 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
bsalomonb5238a72015-05-05 07:49:49 -0700350 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800351 return;
352 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400353 SkRect rect = this->rect();
Brian Salomonec42e152018-05-18 12:52:22 -0400354 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
Brian Osman568bec72018-12-26 16:48:25 -0500355 fDevToUV.apply(verts, 4, sizeof(Vertex), sizeof(SkPoint));
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700356 helper.recordDraw(target, this->gp());
joshualitt95964c62015-02-11 13:45:50 -0800357 }
358
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500359 GrPathUtils::QuadUVMatrix fDevToUV;
joshualitt95964c62015-02-11 13:45:50 -0800360
mtkleindbfd7ab2016-09-01 11:24:54 -0700361 static constexpr int kVertsPerCubic = 4;
362 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800363
Brian Salomon477d0ef2017-07-14 10:12:26 -0400364 typedef BezierTestOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800365};
366
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000367/**
368 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
369 */
Chris Dalton3a778372019-02-07 15:23:36 -0700370class BezierQuadEffects : public GpuGM {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000371public:
372 BezierQuadEffects() {
373 this->setBGColor(0xFFFFFFFF);
374 }
375
376protected:
mtklein36352bf2015-03-25 18:17:31 -0700377 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000378 return SkString("bezier_quad_effects");
379 }
380
mtklein36352bf2015-03-25 18:17:31 -0700381 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700382 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000383 }
384
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000385
Chris Dalton3a778372019-02-07 15:23:36 -0700386 void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
387 SkCanvas* canvas) override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000388 struct Vertex {
389 SkPoint fPosition;
390 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
391 };
392
mtkleindbfd7ab2016-09-01 11:24:54 -0700393 constexpr int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000394 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000395
396 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
397 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400398 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
399 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000400 int row = 0;
401 int col = 0;
Brian Osmancf860852018-10-31 14:04:39 -0400402 SkPMColor4f color = SkPMColor4f::FromBytes_RGBA(0xff000000);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000403
404 for (int i = 0; i < kNumQuads; ++i) {
405 SkPoint baseControlPts[] = {
406 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
407 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
408 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
409 };
Ethan Nicholas1706f842017-11-10 11:58:19 -0500410 for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700411 sk_sp<GrGeometryProcessor> gp;
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500412 GrClipEdgeType et = (GrClipEdgeType)edgeType;
Robert Phillips9da87e02019-02-04 13:26:26 -0500413 gp = GrQuadEffect::Make(color, SkMatrix::I(), et, *context->priv().caps(),
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400414 SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800415 if (!gp) {
416 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000417 }
418
Mike Reeddf85c382017-02-14 10:59:19 -0500419 SkScalar x = col * w;
420 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000421 SkPoint controlPts[] = {
422 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
423 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
424 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
425 };
426 SkPoint chopped[5];
427 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
428
429 SkPaint ctrlPtPaint;
430 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
431 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400432 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000433 }
434
435 SkPaint polyPaint;
436 polyPaint.setColor(0xffA0A0A0);
437 polyPaint.setStrokeWidth(0);
438 polyPaint.setStyle(SkPaint::kStroke_Style);
439 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
440
441 SkPaint choppedPtPaint;
442 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
443
444 for (int c = 0; c < cnt; ++c) {
445 SkPoint* pts = chopped + 2 * c;
446
447 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400448 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000449 }
450
451 SkRect bounds;
Mike Reed92b33352019-08-24 19:39:13 -0400452 bounds.setBounds(pts, 3);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000453
454 SkPaint boundsPaint;
455 boundsPaint.setColor(0xff808080);
456 boundsPaint.setStrokeWidth(0);
457 boundsPaint.setStyle(SkPaint::kStroke_Style);
458 canvas->drawRect(bounds, boundsPaint);
459
robertphillips28a838e2016-06-23 14:07:00 -0700460 GrPaint grPaint;
Brian Salomona1633922017-01-09 11:46:10 -0500461 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
joshualitt3f284d72015-02-11 11:34:58 -0800462
joshualitt95964c62015-02-11 13:45:50 -0800463 GrPathUtils::QuadUVMatrix DevToUV(pts);
464
Robert Phillips7c525e62018-06-12 10:11:12 -0400465 std::unique_ptr<GrDrawOp> op = BezierQuadTestOp::Make(context, gp,
466 bounds, color, DevToUV);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400467 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000468 }
469 ++col;
470 if (numCols == col) {
471 col = 0;
472 ++row;
473 }
474 }
475 }
476 }
477
478private:
479 typedef GM INHERITED;
480};
481
halcanary385fe4d2015-08-26 13:07:48 -0700482DEF_GM(return new BezierConicEffects;)
483DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000484}