blob: dc5439b68d09247773d4248bb23883fdec1aaaad [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"
Robert Phillips3968fcb2019-12-05 16:40:31 -050049#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040050
51#include <memory>
52#include <utility>
53
54class GrAppliedClip;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000055
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000056namespace skiagm {
joshualitt95964c62015-02-11 13:45:50 -080057
Brian Salomon477d0ef2017-07-14 10:12:26 -040058class BezierTestOp : public GrMeshDrawOp {
59public:
60 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
61
Chris Dalton6ce447a2019-06-23 18:07:38 -060062 GrProcessorSet::Analysis finalize(
63 const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
64 GrClampType clampType) override {
Chris Daltonb8fff0d2019-03-05 10:11:58 -070065 return fProcessorSet.finalize(
66 fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
Chris Dalton6ce447a2019-06-23 18:07:38 -060067 &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, caps, clampType, &fColor);
Brian Salomon477d0ef2017-07-14 10:12:26 -040068 }
69
Chris Dalton1706cbf2019-05-21 19:35:29 -060070 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -040071 fProcessorSet.visitProxies(func);
72 }
73
Brian Salomon477d0ef2017-07-14 10:12:26 -040074protected:
Robert Phillips7cd0bfe2019-11-20 16:08:10 -050075 BezierTestOp(GrClipEdgeType et, const SkRect& rect, const SkPMColor4f& color, int32_t classID)
Brian Salomon477d0ef2017-07-14 10:12:26 -040076 : INHERITED(classID)
77 , fRect(rect)
78 , fColor(color)
Robert Phillips7cd0bfe2019-11-20 16:08:10 -050079 , fEdgeType(et)
Brian Salomon477d0ef2017-07-14 10:12:26 -040080 , 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 {
Robert Phillips3968fcb2019-12-05 16:40:31 -050085 auto pipeline = GrSimpleMeshDrawOpHelper::CreatePipeline(flushState,
86 std::move(fProcessorSet),
87 GrPipeline::InputFlags::kNone);
88
89 flushState->executeDrawsAndUploadsForMeshDrawOp(this, chainBounds, pipeline);
Brian Salomon477d0ef2017-07-14 10:12:26 -040090 }
91
Robert Phillips7cd0bfe2019-11-20 16:08:10 -050092 GrClipEdgeType edgeType() const { return fEdgeType; }
Brian Salomon477d0ef2017-07-14 10:12:26 -040093
94 const SkRect& rect() const { return fRect; }
Brian Osmancf860852018-10-31 14:04:39 -040095 const SkPMColor4f& color() const { return fColor; }
Brian Salomon477d0ef2017-07-14 10:12:26 -040096
97private:
Brian Salomon477d0ef2017-07-14 10:12:26 -040098 SkRect fRect;
Brian Osmancf860852018-10-31 14:04:39 -040099 SkPMColor4f fColor;
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500100 GrClipEdgeType fEdgeType;
Brian Salomon477d0ef2017-07-14 10:12:26 -0400101 GrProcessorSet fProcessorSet;
102
103 typedef GrMeshDrawOp INHERITED;
104};
105
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000106/**
107 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
108 */
Brian Salomon477d0ef2017-07-14 10:12:26 -0400109class BezierConicTestOp : public BezierTestOp {
Chris Daltonfebbffa2017-06-08 13:12:02 -0600110public:
111 DEFINE_OP_CLASS_ID
112
113 const char* name() const override { return "BezierConicTestOp"; }
114
Robert Phillipsbe9aff22019-02-15 11:33:22 -0500115 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500116 GrClipEdgeType et,
Robert Phillips7c525e62018-06-12 10:11:12 -0400117 const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400118 const SkPMColor4f& color,
Robert Phillips7c525e62018-06-12 10:11:12 -0400119 const SkMatrix& klm) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500120 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400121
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500122 return pool->allocate<BezierConicTestOp>(et, rect, color, klm);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600123 }
124
125private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400126 friend class ::GrOpMemoryPool; // for ctor
127
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500128 BezierConicTestOp(GrClipEdgeType et, const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400129 const SkPMColor4f& color, const SkMatrix& klm)
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500130 : INHERITED(et, rect, color, ClassID()), fKLM(klm) {}
Brian Salomon477d0ef2017-07-14 10:12:26 -0400131
Chris Daltonfebbffa2017-06-08 13:12:02 -0600132 struct Vertex {
133 SkPoint fPosition;
134 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
135 };
136
Brian Salomon91326c32017-08-09 16:02:19 -0400137 void onPrepareDraws(Target* target) override {
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500138 GrGeometryProcessor* gp = GrConicEffect::Make(target->allocator(), this->color(),
139 SkMatrix::I(), this->edgeType(),
140 target->caps(), SkMatrix::I(), false);
141 if (!gp) {
142 return;
143 }
144
145 SkASSERT(gp->vertexStride() == sizeof(Vertex));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000146 QuadHelper helper(target, sizeof(Vertex), 1);
147 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600148 if (!verts) {
149 return;
150 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400151 SkRect rect = this->rect();
Cary Clark74f623d2017-11-06 20:02:02 -0500152 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect.fLeft, rect.fTop, rect.fRight,
153 rect.fBottom, sizeof(Vertex));
Chris Daltonfebbffa2017-06-08 13:12:02 -0600154 for (int v = 0; v < 4; ++v) {
Cary Clarke4442cb2017-10-18 11:46:18 -0400155 SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
156 fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600157 }
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700158
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500159 helper.recordDraw(target, gp);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600160 }
161
162 SkMatrix fKLM;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600163
164 static constexpr int kVertsPerCubic = 4;
165 static constexpr int kIndicesPerCubic = 6;
166
Brian Salomon477d0ef2017-07-14 10:12:26 -0400167 typedef BezierTestOp INHERITED;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600168};
169
170
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000171/**
172 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
173 */
Chris Dalton3a778372019-02-07 15:23:36 -0700174class BezierConicEffects : public GpuGM {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000175public:
176 BezierConicEffects() {
177 this->setBGColor(0xFFFFFFFF);
178 }
179
180protected:
Robert Phillips98f3fd92019-11-21 13:16:21 -0500181 static const int kNumConics = 10;
182 static const int kCellWidth = 128;
183 static const int kCellHeight = 128;
184
mtklein36352bf2015-03-25 18:17:31 -0700185 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000186 return SkString("bezier_conic_effects");
187 }
188
mtklein36352bf2015-03-25 18:17:31 -0700189 SkISize onISize() override {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500190 return SkISize::Make(kGrClipEdgeTypeCnt*kCellWidth, kNumConics*kCellHeight);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000191 }
192
Chris Dalton3a778372019-02-07 15:23:36 -0700193 void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
194 SkCanvas* canvas) override {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500195
196 const SkScalar w = kCellWidth, h = kCellHeight;
197 const SkPMColor4f kOpaqueBlack = SkPMColor4f::FromBytes_RGBA(0xff000000);
198
199 const SkPoint baseControlPts[kNumConics][3] = {
200 { { 0.31f * w, 0.01f * h}, { 0.48f * w, 0.74f * h }, { 0.19f * w, 0.33f * h } },
201 { { 0.00f * w, 0.07f * h}, { 0.30f * w, 0.70f * h }, { 0.47f * w, 0.37f * h } },
202 { { 0.15f * w, 0.23f * h}, { 0.49f * w, 0.87f * h }, { 0.85f * w, 0.66f * h } },
203 { { 0.09f * w, 0.15f * h}, { 0.42f * w, 0.33f * h }, { 0.17f * w, 0.38f * h } },
204 { { 0.98f * w, 0.54f * h}, { 0.83f * w, 0.91f * h }, { 0.62f * w, 0.40f * h } },
205 { { 0.96f * w, 0.65f * h}, { 0.03f * w, 0.79f * h }, { 0.24f * w, 0.56f * h } },
206 { { 0.57f * w, 0.12f * h}, { 0.33f * w, 0.67f * h }, { 0.59f * w, 0.33f * h } },
207 { { 0.12f * w, 0.72f * h}, { 0.69f * w, 0.85f * h }, { 0.46f * w, 0.32f * h } },
208 { { 0.27f * w, 0.49f * h}, { 0.41f * w, 0.02f * h }, { 0.11f * w, 0.42f * h } },
209 { { 0.40f * w, 0.13f * h}, { 0.83f * w, 0.30f * h }, { 0.31f * w, 0.68f * h } },
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000210 };
Robert Phillips98f3fd92019-11-21 13:16:21 -0500211 const SkScalar weights[kNumConics] = { 0.62f, 0.01f, 0.95f, 1.48f, 0.37f,
212 0.66f, 0.15f, 0.14f, 0.61f, 1.4f };
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000213
Robert Phillips98f3fd92019-11-21 13:16:21 -0500214 SkPaint ctrlPtPaint;
215 ctrlPtPaint.setColor(SK_ColorRED);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000216
Robert Phillips98f3fd92019-11-21 13:16:21 -0500217 SkPaint choppedPtPaint;
218 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000219
Robert Phillips98f3fd92019-11-21 13:16:21 -0500220 SkPaint polyPaint;
221 polyPaint.setColor(0xffA0A0A0);
222 polyPaint.setStrokeWidth(0);
223 polyPaint.setStyle(SkPaint::kStroke_Style);
224
225 SkPaint boundsPaint;
226 boundsPaint.setColor(0xff808080);
227 boundsPaint.setStrokeWidth(0);
228 boundsPaint.setStyle(SkPaint::kStroke_Style);
229
230
231 for (int row = 0; row < kNumConics; ++row) {
232 for(int col = 0; col < kGrClipEdgeTypeCnt; ++col) {
233 GrClipEdgeType et = (GrClipEdgeType) col;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000234
Mike Reeddf85c382017-02-14 10:59:19 -0500235 SkScalar x = col * w;
236 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000237 SkPoint controlPts[] = {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500238 {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY},
239 {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY},
240 {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY}
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000241 };
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000242
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000243 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400244 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000245 }
246
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000247 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
248
Robert Phillips98f3fd92019-11-21 13:16:21 -0500249 SkConic dst[4];
250 SkMatrix klm;
251 int cnt = ChopConic(controlPts, dst, weights[row]);
252 GrPathUtils::getConicKLM(controlPts, weights[row], &klm);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000253
254 for (int c = 0; c < cnt; ++c) {
255 SkPoint* pts = dst[c].fPts;
256 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400257 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000258 }
259
260 SkRect bounds;
Mike Reed92b33352019-08-24 19:39:13 -0400261 bounds.setBounds(pts, 3);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000262
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000263 canvas->drawRect(bounds, boundsPaint);
264
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500265 std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(context, et, bounds,
Robert Phillips98f3fd92019-11-21 13:16:21 -0500266 kOpaqueBlack, klm);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400267 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000268 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000269 }
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.
Robert Phillips98f3fd92019-11-21 13:16:21 -0500279 static int SplitConic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000280 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
Robert Phillips98f3fd92019-11-21 13:16:21 -0500299 // Calls SplitConic on the entire conic and then once more on each subsection.
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000300 // 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).
Robert Phillips98f3fd92019-11-21 13:16:21 -0500302 static int ChopConic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000303 SkConic dstTemp[2];
Robert Phillips98f3fd92019-11-21 13:16:21 -0500304 int conicCnt = SplitConic(src, dstTemp, weight);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000305 if (2 == conicCnt) {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500306 int conicCnt2 = SplitConic(dstTemp[0].fPts, dst, dstTemp[0].fW);
307 conicCnt = conicCnt2 + SplitConic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000308 } 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
Michael Ludwig28b0c5d2019-12-19 14:51:00 -0500324 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500325 GrClipEdgeType et,
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
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500331 return pool->allocate<BezierQuadTestOp>(et, 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
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500337 BezierQuadTestOp(GrClipEdgeType et, const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400338 const SkPMColor4f& color, const GrPathUtils::QuadUVMatrix& devToUV)
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500339 : INHERITED(et, 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 {
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500347 GrGeometryProcessor* gp = GrQuadEffect::Make(target->allocator(), this->color(),
348 SkMatrix::I(), this->edgeType(),
349 target->caps(), SkMatrix::I(), false);
350 if (!gp) {
351 return;
352 }
353
354 SkASSERT(gp->vertexStride() == sizeof(Vertex));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000355 QuadHelper helper(target, sizeof(Vertex), 1);
356 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
bsalomonb5238a72015-05-05 07:49:49 -0700357 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800358 return;
359 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400360 SkRect rect = this->rect();
Brian Salomonec42e152018-05-18 12:52:22 -0400361 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
Brian Osman568bec72018-12-26 16:48:25 -0500362 fDevToUV.apply(verts, 4, sizeof(Vertex), sizeof(SkPoint));
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500363 helper.recordDraw(target, gp);
joshualitt95964c62015-02-11 13:45:50 -0800364 }
365
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500366 GrPathUtils::QuadUVMatrix fDevToUV;
joshualitt95964c62015-02-11 13:45:50 -0800367
mtkleindbfd7ab2016-09-01 11:24:54 -0700368 static constexpr int kVertsPerCubic = 4;
369 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800370
Brian Salomon477d0ef2017-07-14 10:12:26 -0400371 typedef BezierTestOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800372};
373
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000374/**
375 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
376 */
Chris Dalton3a778372019-02-07 15:23:36 -0700377class BezierQuadEffects : public GpuGM {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000378public:
379 BezierQuadEffects() {
380 this->setBGColor(0xFFFFFFFF);
381 }
382
383protected:
Robert Phillips98f3fd92019-11-21 13:16:21 -0500384 static const int kNumQuads = 5;
385 static const int kCellWidth = 128;
386 static const int kCellHeight = 128;
387
mtklein36352bf2015-03-25 18:17:31 -0700388 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000389 return SkString("bezier_quad_effects");
390 }
391
mtklein36352bf2015-03-25 18:17:31 -0700392 SkISize onISize() override {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500393 return SkISize::Make(kGrClipEdgeTypeCnt*kCellWidth, kNumQuads*kCellHeight);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000394 }
395
Chris Dalton3a778372019-02-07 15:23:36 -0700396 void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext,
397 SkCanvas* canvas) override {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500398
399 const SkScalar w = kCellWidth, h = kCellHeight;
400 const SkPMColor4f kOpaqueBlack = SkPMColor4f::FromBytes_RGBA(0xff000000);
401
402 const SkPoint baseControlPts[kNumQuads][3] = {
403 { { 0.31f * w, 0.01f * h}, { 0.48f * w, 0.74f * h }, { 0.19f * w, 0.33f * h } },
404 { { 0.00f * w, 0.07f * h}, { 0.30f * w, 0.70f * h }, { 0.47f * w, 0.37f * h } },
405 { { 0.15f * w, 0.23f * h}, { 0.49f * w, 0.87f * h }, { 0.85f * w, 0.66f * h } },
406 { { 0.09f * w, 0.15f * h}, { 0.42f * w, 0.33f * h }, { 0.17f * w, 0.38f * h } },
407 { { 0.98f * w, 0.54f * h}, { 0.83f * w, 0.91f * h }, { 0.62f * w, 0.40f * h } },
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000408 };
409
Robert Phillips98f3fd92019-11-21 13:16:21 -0500410 SkPaint ctrlPtPaint;
411 ctrlPtPaint.setColor(SK_ColorRED);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000412
Robert Phillips98f3fd92019-11-21 13:16:21 -0500413 SkPaint choppedPtPaint;
414 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000415
Robert Phillips98f3fd92019-11-21 13:16:21 -0500416 SkPaint polyPaint;
417 polyPaint.setColor(0xffA0A0A0);
418 polyPaint.setStrokeWidth(0);
419 polyPaint.setStyle(SkPaint::kStroke_Style);
420
421 SkPaint boundsPaint;
422 boundsPaint.setColor(0xff808080);
423 boundsPaint.setStrokeWidth(0);
424 boundsPaint.setStyle(SkPaint::kStroke_Style);
425
426 for (int row = 0; row < kNumQuads; ++row) {
427 for(int col = 0; col < kGrClipEdgeTypeCnt; ++col) {
428 GrClipEdgeType et = (GrClipEdgeType) col;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000429
Mike Reeddf85c382017-02-14 10:59:19 -0500430 SkScalar x = col * w;
431 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000432 SkPoint controlPts[] = {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500433 {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY},
434 {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY},
435 {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY}
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000436 };
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000437
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000438 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400439 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000440 }
441
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000442 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
443
Robert Phillips98f3fd92019-11-21 13:16:21 -0500444 SkPoint chopped[5];
445 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000446
447 for (int c = 0; c < cnt; ++c) {
448 SkPoint* pts = chopped + 2 * c;
449
450 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400451 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000452 }
453
454 SkRect bounds;
Mike Reed92b33352019-08-24 19:39:13 -0400455 bounds.setBounds(pts, 3);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000456
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000457 canvas->drawRect(bounds, boundsPaint);
458
joshualitt95964c62015-02-11 13:45:50 -0800459 GrPathUtils::QuadUVMatrix DevToUV(pts);
460
Robert Phillips98f3fd92019-11-21 13:16:21 -0500461 std::unique_ptr<GrDrawOp> op = BezierQuadTestOp::Make(context, et, bounds,
462 kOpaqueBlack, DevToUV);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400463 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000464 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000465 }
466 }
467 }
468
469private:
470 typedef GM INHERITED;
471};
472
halcanary385fe4d2015-08-26 13:07:48 -0700473DEF_GM(return new BezierConicEffects;)
474DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000475}