blob: b30e44267069e0f202af55a7e702d9f6b29e1c4f [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"
Robert Phillipsb7bfbc22020-07-01 12:55:01 -040023#include "include/gpu/GrRecordingContext.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040024#include "include/private/GrTypesPriv.h"
25#include "include/private/SkColorData.h"
26#include "include/utils/SkRandom.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "src/core/SkGeometry.h"
28#include "src/core/SkPointPriv.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040029#include "src/gpu/GrCaps.h"
Adlai Hollera0693042020-10-14 11:23:11 -040030#include "src/gpu/GrDirectContextPriv.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040031#include "src/gpu/GrGeometryProcessor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050032#include "src/gpu/GrMemoryPool.h"
33#include "src/gpu/GrOpFlushState.h"
Robert Phillipsce978572020-02-28 11:56:44 -050034#include "src/gpu/GrOpsRenderPass.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040035#include "src/gpu/GrPaint.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040036#include "src/gpu/GrProcessorAnalysis.h"
37#include "src/gpu/GrProcessorSet.h"
Robert Phillipsce978572020-02-28 11:56:44 -050038#include "src/gpu/GrProgramInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050039#include "src/gpu/GrRecordingContextPriv.h"
Brian Salomoneebe7352020-12-09 16:37:04 -050040#include "src/gpu/GrSurfaceDrawContext.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040041#include "src/gpu/GrUserStencilSettings.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050042#include "src/gpu/effects/GrBezierEffect.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040043#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
Michael Ludwig663afe52019-06-03 16:46:19 -040044#include "src/gpu/geometry/GrPathUtils.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040045#include "src/gpu/ops/GrDrawOp.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050046#include "src/gpu/ops/GrMeshDrawOp.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040047#include "src/gpu/ops/GrOp.h"
Robert Phillips3968fcb2019-12-05 16:40:31 -050048#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040049
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(
Chris Dalton57ab06c2021-04-22 12:57:28 -060062 const GrCaps& caps, const GrAppliedClip* clip, GrClampType clampType) override {
Chris Daltonb8fff0d2019-03-05 10:11:58 -070063 return fProcessorSet.finalize(
64 fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
Chris Dalton57ab06c2021-04-22 12:57:28 -060065 &GrUserStencilSettings::kUnused, caps, clampType, &fColor);
Brian Salomon477d0ef2017-07-14 10:12:26 -040066 }
67
Robert Phillips294723d2021-06-17 09:23:58 -040068 void visitProxies(const GrVisitProxyFunc& func) const override {
Robert Phillips4f93c572020-03-18 08:13:53 -040069 if (fProgramInfo) {
70 fProgramInfo->visitFPProxies(func);
71 } else {
72 fProcessorSet.visitProxies(func);
73 }
Robert Phillipsb493eeb2017-09-13 13:10:52 -040074 }
75
Brian Salomon477d0ef2017-07-14 10:12:26 -040076protected:
John Stiles3b2c06c2020-06-17 12:45:57 -040077 BezierTestOp(const SkRect& rect, const SkPMColor4f& color, int32_t classID)
Brian Salomon477d0ef2017-07-14 10:12:26 -040078 : INHERITED(classID)
79 , fRect(rect)
80 , fColor(color)
Brian Salomon477d0ef2017-07-14 10:12:26 -040081 , fProcessorSet(SkBlendMode::kSrc) {
Greg Daniel5faf4742019-10-01 15:14:44 -040082 this->setBounds(rect, HasAABloat::kYes, IsHairline::kNo);
Brian Salomon477d0ef2017-07-14 10:12:26 -040083 }
84
Robert Phillipsce978572020-02-28 11:56:44 -050085 virtual GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) = 0;
Robert Phillips3968fcb2019-12-05 16:40:31 -050086
Robert Phillips2669a7b2020-03-12 12:07:19 -040087 GrProgramInfo* programInfo() override { return fProgramInfo; }
88
Robert Phillips4133dc42020-03-11 15:55:55 -040089 void onCreateProgramInfo(const GrCaps* caps,
90 SkArenaAlloc* arena,
Adlai Hollere2296f72020-11-19 13:41:26 -050091 const GrSurfaceProxyView& writeView,
Chris Dalton6aaf00f2021-07-13 13:26:39 -060092 bool usesMSAASurface,
Robert Phillips4133dc42020-03-11 15:55:55 -040093 GrAppliedClip&& appliedClip,
John Stiles52cb1d02021-06-02 11:58:05 -040094 const GrDstProxyView& dstProxyView,
Greg Daniel42dbca52020-11-20 10:22:43 -050095 GrXferBarrierFlags renderPassXferBarriers,
96 GrLoadOp colorLoadOp) override {
Robert Phillipsce978572020-02-28 11:56:44 -050097 auto gp = this->makeGP(*caps, arena);
98 if (!gp) {
Robert Phillips4133dc42020-03-11 15:55:55 -040099 return;
Robert Phillipsce978572020-02-28 11:56:44 -0500100 }
101
102 GrPipeline::InputFlags flags = GrPipeline::InputFlags::kNone;
103
Brian Salomon8afde5f2020-04-01 16:22:00 -0400104 fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps, arena, writeView,
Robert Phillips4133dc42020-03-11 15:55:55 -0400105 std::move(appliedClip),
106 dstProxyView, gp,
107 std::move(fProcessorSet),
108 GrPrimitiveType::kTriangles,
Greg Danield358cbe2020-09-11 09:33:54 -0400109 renderPassXferBarriers,
Greg Daniel42dbca52020-11-20 10:22:43 -0500110 colorLoadOp,
Robert Phillips4133dc42020-03-11 15:55:55 -0400111 flags);
Robert Phillipsce978572020-02-28 11:56:44 -0500112 }
113
Robert Phillipsce978572020-02-28 11:56:44 -0500114 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) final {
115 if (!fProgramInfo) {
Robert Phillips4133dc42020-03-11 15:55:55 -0400116 this->createProgramInfo(flushState);
Robert Phillipsce978572020-02-28 11:56:44 -0500117 }
118
119 if (!fProgramInfo) {
120 return;
121 }
122
Chris Dalton765ed362020-03-16 17:34:44 -0600123 flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
Robert Phillips787fd9d2021-03-22 14:48:09 -0400124 flushState->bindTextures(fProgramInfo->geomProc(), nullptr, fProgramInfo->pipeline());
Chris Dalton765ed362020-03-16 17:34:44 -0600125 flushState->drawMesh(*fMesh);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400126 }
127
Brian Salomon477d0ef2017-07-14 10:12:26 -0400128 const SkRect& rect() const { return fRect; }
Brian Osmancf860852018-10-31 14:04:39 -0400129 const SkPMColor4f& color() const { return fColor; }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400130
Robert Phillipsce978572020-02-28 11:56:44 -0500131protected:
Chris Daltoneb694b72020-03-16 09:25:50 -0600132 GrSimpleMesh* fMesh = nullptr; // filled in by the derived classes
Robert Phillipsce978572020-02-28 11:56:44 -0500133
Brian Salomon477d0ef2017-07-14 10:12:26 -0400134private:
Robert Phillipsce978572020-02-28 11:56:44 -0500135 SkRect fRect;
136 SkPMColor4f fColor;
Robert Phillipsce978572020-02-28 11:56:44 -0500137 GrProcessorSet fProcessorSet;
138 GrProgramInfo* fProgramInfo = nullptr;
Brian Salomon477d0ef2017-07-14 10:12:26 -0400139
John Stiles7571f9e2020-09-02 22:42:33 -0400140 using INHERITED = GrMeshDrawOp;
Brian Salomon477d0ef2017-07-14 10:12:26 -0400141};
142
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000143/**
144 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
145 */
Brian Salomon477d0ef2017-07-14 10:12:26 -0400146class BezierConicTestOp : public BezierTestOp {
Chris Daltonfebbffa2017-06-08 13:12:02 -0600147public:
148 DEFINE_OP_CLASS_ID
149
Robert Phillipsce978572020-02-28 11:56:44 -0500150 const char* name() const final { return "BezierConicTestOp"; }
Chris Daltonfebbffa2017-06-08 13:12:02 -0600151
Herb Derbyc76d4092020-10-07 16:46:15 -0400152 static GrOp::Owner Make(GrRecordingContext* context,
153 const SkRect& rect,
154 const SkPMColor4f& color,
155 const SkMatrix& klm) {
156 return GrOp::Make<BezierConicTestOp>(context, rect, color, klm);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600157 }
158
159private:
Herb Derbyc76d4092020-10-07 16:46:15 -0400160 friend class ::GrOp; // for ctor
Robert Phillips7c525e62018-06-12 10:11:12 -0400161
John Stiles3b2c06c2020-06-17 12:45:57 -0400162 BezierConicTestOp(const SkRect& rect, const SkPMColor4f& color, const SkMatrix& klm)
163 : INHERITED(rect, color, ClassID())
164 , fKLM(klm) {}
Brian Salomon477d0ef2017-07-14 10:12:26 -0400165
Chris Daltonfebbffa2017-06-08 13:12:02 -0600166 struct Vertex {
167 SkPoint fPosition;
168 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
169 };
170
Robert Phillipsce978572020-02-28 11:56:44 -0500171 GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) final {
John Stiles3b2c06c2020-06-17 12:45:57 -0400172 auto tmp = GrConicEffect::Make(arena, this->color(), SkMatrix::I(), caps, SkMatrix::I(),
173 false);
Robert Phillipsce978572020-02-28 11:56:44 -0500174 if (!tmp) {
175 return nullptr;
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500176 }
Robert Phillipsce978572020-02-28 11:56:44 -0500177 SkASSERT(tmp->vertexStride() == sizeof(Vertex));
178 return tmp;
179 }
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500180
Robert Phillips71143952021-06-17 14:55:07 -0400181 void onPrepareDraws(GrMeshDrawTarget* target) final {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000182 QuadHelper helper(target, sizeof(Vertex), 1);
183 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600184 if (!verts) {
185 return;
186 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400187 SkRect rect = this->rect();
Robert Phillipsce978572020-02-28 11:56:44 -0500188 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
Chris Daltonfebbffa2017-06-08 13:12:02 -0600189 for (int v = 0; v < 4; ++v) {
Cary Clarke4442cb2017-10-18 11:46:18 -0400190 SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
191 fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600192 }
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700193
Robert Phillipsce978572020-02-28 11:56:44 -0500194 fMesh = helper.mesh();
Chris Daltonfebbffa2017-06-08 13:12:02 -0600195 }
196
197 SkMatrix fKLM;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600198
199 static constexpr int kVertsPerCubic = 4;
200 static constexpr int kIndicesPerCubic = 6;
201
John Stiles7571f9e2020-09-02 22:42:33 -0400202 using INHERITED = BezierTestOp;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600203};
204
205
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000206/**
207 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
208 */
Chris Dalton3a778372019-02-07 15:23:36 -0700209class BezierConicEffects : public GpuGM {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000210public:
211 BezierConicEffects() {
212 this->setBGColor(0xFFFFFFFF);
213 }
214
215protected:
Robert Phillips98f3fd92019-11-21 13:16:21 -0500216 static const int kNumConics = 10;
217 static const int kCellWidth = 128;
218 static const int kCellHeight = 128;
219
mtklein36352bf2015-03-25 18:17:31 -0700220 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000221 return SkString("bezier_conic_effects");
222 }
223
mtklein36352bf2015-03-25 18:17:31 -0700224 SkISize onISize() override {
John Stiles3b2c06c2020-06-17 12:45:57 -0400225 return SkISize::Make(kCellWidth, kNumConics*kCellHeight);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000226 }
227
Brian Salomon1aa1f5f2020-12-11 17:25:17 -0500228 void onDraw(GrRecordingContext* context, GrSurfaceDrawContext* surfaceDrawContext,
Chris Dalton3a778372019-02-07 15:23:36 -0700229 SkCanvas* canvas) override {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500230
231 const SkScalar w = kCellWidth, h = kCellHeight;
232 const SkPMColor4f kOpaqueBlack = SkPMColor4f::FromBytes_RGBA(0xff000000);
233
234 const SkPoint baseControlPts[kNumConics][3] = {
235 { { 0.31f * w, 0.01f * h}, { 0.48f * w, 0.74f * h }, { 0.19f * w, 0.33f * h } },
236 { { 0.00f * w, 0.07f * h}, { 0.30f * w, 0.70f * h }, { 0.47f * w, 0.37f * h } },
237 { { 0.15f * w, 0.23f * h}, { 0.49f * w, 0.87f * h }, { 0.85f * w, 0.66f * h } },
238 { { 0.09f * w, 0.15f * h}, { 0.42f * w, 0.33f * h }, { 0.17f * w, 0.38f * h } },
239 { { 0.98f * w, 0.54f * h}, { 0.83f * w, 0.91f * h }, { 0.62f * w, 0.40f * h } },
240 { { 0.96f * w, 0.65f * h}, { 0.03f * w, 0.79f * h }, { 0.24f * w, 0.56f * h } },
241 { { 0.57f * w, 0.12f * h}, { 0.33f * w, 0.67f * h }, { 0.59f * w, 0.33f * h } },
242 { { 0.12f * w, 0.72f * h}, { 0.69f * w, 0.85f * h }, { 0.46f * w, 0.32f * h } },
243 { { 0.27f * w, 0.49f * h}, { 0.41f * w, 0.02f * h }, { 0.11f * w, 0.42f * h } },
244 { { 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 +0000245 };
Robert Phillips98f3fd92019-11-21 13:16:21 -0500246 const SkScalar weights[kNumConics] = { 0.62f, 0.01f, 0.95f, 1.48f, 0.37f,
247 0.66f, 0.15f, 0.14f, 0.61f, 1.4f };
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000248
Robert Phillips98f3fd92019-11-21 13:16:21 -0500249 SkPaint ctrlPtPaint;
250 ctrlPtPaint.setColor(SK_ColorRED);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000251
Robert Phillips98f3fd92019-11-21 13:16:21 -0500252 SkPaint choppedPtPaint;
253 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000254
Robert Phillips98f3fd92019-11-21 13:16:21 -0500255 SkPaint polyPaint;
256 polyPaint.setColor(0xffA0A0A0);
257 polyPaint.setStrokeWidth(0);
258 polyPaint.setStyle(SkPaint::kStroke_Style);
259
260 SkPaint boundsPaint;
261 boundsPaint.setColor(0xff808080);
262 boundsPaint.setStrokeWidth(0);
263 boundsPaint.setStyle(SkPaint::kStroke_Style);
264
265
266 for (int row = 0; row < kNumConics; ++row) {
John Stiles3b2c06c2020-06-17 12:45:57 -0400267 SkScalar x = 0;
268 SkScalar y = row * h;
269 SkPoint controlPts[] = {
270 {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY},
271 {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY},
272 {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY}
273 };
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000274
John Stiles3b2c06c2020-06-17 12:45:57 -0400275 for (int i = 0; i < 3; ++i) {
276 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
277 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000278
John Stiles3b2c06c2020-06-17 12:45:57 -0400279 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
280
281 SkConic dst[4];
282 SkMatrix klm;
283 int cnt = ChopConic(controlPts, dst, weights[row]);
284 GrPathUtils::getConicKLM(controlPts, weights[row], &klm);
285
286 for (int c = 0; c < cnt; ++c) {
287 SkPoint* pts = dst[c].fPts;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000288 for (int i = 0; i < 3; ++i) {
John Stiles3b2c06c2020-06-17 12:45:57 -0400289 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000290 }
291
John Stiles3b2c06c2020-06-17 12:45:57 -0400292 SkRect bounds;
293 bounds.setBounds(pts, 3);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000294
John Stiles3b2c06c2020-06-17 12:45:57 -0400295 canvas->drawRect(bounds, boundsPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000296
Herb Derbyc76d4092020-10-07 16:46:15 -0400297 GrOp::Owner op = BezierConicTestOp::Make(context, bounds,
298 kOpaqueBlack, klm);
Brian Salomon1aa1f5f2020-12-11 17:25:17 -0500299 surfaceDrawContext->addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000300 }
301 }
302 }
303
304private:
305 // Uses the max curvature function for quads to estimate
306 // where to chop the conic. If the max curvature is not
307 // found along the curve segment it will return 1 and
308 // dst[0] is the original conic. If it returns 2 the dst[0]
309 // and dst[1] are the two new conics.
Robert Phillips98f3fd92019-11-21 13:16:21 -0500310 static int SplitConic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000311 SkScalar t = SkFindQuadMaxCurvature(src);
Chris Dalton1d474dd2018-07-24 01:08:31 -0600312 if (t == 0 || t == 1) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000313 if (dst) {
314 dst[0].set(src, weight);
315 }
316 return 1;
317 } else {
318 if (dst) {
319 SkConic conic;
320 conic.set(src, weight);
caryclark414c4292016-09-26 11:03:54 -0700321 if (!conic.chopAt(t, dst)) {
322 dst[0].set(src, weight);
323 return 1;
324 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000325 }
326 return 2;
327 }
328 }
329
Robert Phillips98f3fd92019-11-21 13:16:21 -0500330 // Calls SplitConic on the entire conic and then once more on each subsection.
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000331 // Most cases will result in either 1 conic (chop point is not within t range)
332 // or 3 points (split once and then one subsection is split again).
Robert Phillips98f3fd92019-11-21 13:16:21 -0500333 static int ChopConic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000334 SkConic dstTemp[2];
Robert Phillips98f3fd92019-11-21 13:16:21 -0500335 int conicCnt = SplitConic(src, dstTemp, weight);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000336 if (2 == conicCnt) {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500337 int conicCnt2 = SplitConic(dstTemp[0].fPts, dst, dstTemp[0].fW);
338 conicCnt = conicCnt2 + SplitConic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000339 } else {
340 dst[0] = dstTemp[0];
341 }
342 return conicCnt;
343 }
344
John Stiles7571f9e2020-09-02 22:42:33 -0400345 using INHERITED = GM;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000346};
347
348//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800349
Brian Salomon477d0ef2017-07-14 10:12:26 -0400350class BezierQuadTestOp : public BezierTestOp {
joshualitt95964c62015-02-11 13:45:50 -0800351public:
Brian Salomon25a88092016-12-01 09:36:50 -0500352 DEFINE_OP_CLASS_ID
Brian Salomon6b316e92016-12-16 09:35:49 -0500353 const char* name() const override { return "BezierQuadTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -0800354
Herb Derbyc76d4092020-10-07 16:46:15 -0400355 static GrOp::Owner Make(GrRecordingContext* context,
356 const SkRect& rect,
357 const SkPMColor4f& color,
358 const GrPathUtils::QuadUVMatrix& devToUV) {
359 return GrOp::Make<BezierQuadTestOp>(context, rect, color, devToUV);
joshualitt95964c62015-02-11 13:45:50 -0800360 }
361
362private:
Herb Derbyc76d4092020-10-07 16:46:15 -0400363 friend class ::GrOp; // for ctor
Robert Phillips7c525e62018-06-12 10:11:12 -0400364
John Stiles3b2c06c2020-06-17 12:45:57 -0400365 BezierQuadTestOp(const SkRect& rect, const SkPMColor4f& color,
366 const GrPathUtils::QuadUVMatrix& devToUV)
367 : INHERITED(rect, color, ClassID())
368 , fDevToUV(devToUV) {}
joshualitt95964c62015-02-11 13:45:50 -0800369
370 struct Vertex {
371 SkPoint fPosition;
372 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
373 };
374
Robert Phillipsce978572020-02-28 11:56:44 -0500375 GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) final {
John Stiles3b2c06c2020-06-17 12:45:57 -0400376 auto tmp = GrQuadEffect::Make(arena, this->color(), SkMatrix::I(), caps, SkMatrix::I(),
377 false);
Robert Phillipsce978572020-02-28 11:56:44 -0500378 if (!tmp) {
379 return nullptr;
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500380 }
Robert Phillipsce978572020-02-28 11:56:44 -0500381 SkASSERT(tmp->vertexStride() == sizeof(Vertex));
382 return tmp;
383 }
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500384
Robert Phillips71143952021-06-17 14:55:07 -0400385 void onPrepareDraws(GrMeshDrawTarget* target) final {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000386 QuadHelper helper(target, sizeof(Vertex), 1);
387 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
bsalomonb5238a72015-05-05 07:49:49 -0700388 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800389 return;
390 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400391 SkRect rect = this->rect();
Brian Salomonec42e152018-05-18 12:52:22 -0400392 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
Brian Osman568bec72018-12-26 16:48:25 -0500393 fDevToUV.apply(verts, 4, sizeof(Vertex), sizeof(SkPoint));
Robert Phillipsce978572020-02-28 11:56:44 -0500394
395 fMesh = helper.mesh();
joshualitt95964c62015-02-11 13:45:50 -0800396 }
397
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500398 GrPathUtils::QuadUVMatrix fDevToUV;
joshualitt95964c62015-02-11 13:45:50 -0800399
mtkleindbfd7ab2016-09-01 11:24:54 -0700400 static constexpr int kVertsPerCubic = 4;
401 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800402
John Stiles7571f9e2020-09-02 22:42:33 -0400403 using INHERITED = BezierTestOp;
joshualitt95964c62015-02-11 13:45:50 -0800404};
405
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000406/**
407 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
408 */
Chris Dalton3a778372019-02-07 15:23:36 -0700409class BezierQuadEffects : public GpuGM {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000410public:
411 BezierQuadEffects() {
412 this->setBGColor(0xFFFFFFFF);
413 }
414
415protected:
Robert Phillips98f3fd92019-11-21 13:16:21 -0500416 static const int kNumQuads = 5;
417 static const int kCellWidth = 128;
418 static const int kCellHeight = 128;
419
mtklein36352bf2015-03-25 18:17:31 -0700420 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000421 return SkString("bezier_quad_effects");
422 }
423
mtklein36352bf2015-03-25 18:17:31 -0700424 SkISize onISize() override {
John Stiles3b2c06c2020-06-17 12:45:57 -0400425 return SkISize::Make(kCellWidth, kNumQuads*kCellHeight);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000426 }
427
Brian Salomon1aa1f5f2020-12-11 17:25:17 -0500428 void onDraw(GrRecordingContext* context, GrSurfaceDrawContext* surfaceDrawContext,
Chris Dalton3a778372019-02-07 15:23:36 -0700429 SkCanvas* canvas) override {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500430
431 const SkScalar w = kCellWidth, h = kCellHeight;
432 const SkPMColor4f kOpaqueBlack = SkPMColor4f::FromBytes_RGBA(0xff000000);
433
434 const SkPoint baseControlPts[kNumQuads][3] = {
435 { { 0.31f * w, 0.01f * h}, { 0.48f * w, 0.74f * h }, { 0.19f * w, 0.33f * h } },
436 { { 0.00f * w, 0.07f * h}, { 0.30f * w, 0.70f * h }, { 0.47f * w, 0.37f * h } },
437 { { 0.15f * w, 0.23f * h}, { 0.49f * w, 0.87f * h }, { 0.85f * w, 0.66f * h } },
438 { { 0.09f * w, 0.15f * h}, { 0.42f * w, 0.33f * h }, { 0.17f * w, 0.38f * h } },
439 { { 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 +0000440 };
441
Robert Phillips98f3fd92019-11-21 13:16:21 -0500442 SkPaint ctrlPtPaint;
443 ctrlPtPaint.setColor(SK_ColorRED);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000444
Robert Phillips98f3fd92019-11-21 13:16:21 -0500445 SkPaint choppedPtPaint;
446 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000447
Robert Phillips98f3fd92019-11-21 13:16:21 -0500448 SkPaint polyPaint;
449 polyPaint.setColor(0xffA0A0A0);
450 polyPaint.setStrokeWidth(0);
451 polyPaint.setStyle(SkPaint::kStroke_Style);
452
453 SkPaint boundsPaint;
454 boundsPaint.setColor(0xff808080);
455 boundsPaint.setStrokeWidth(0);
456 boundsPaint.setStyle(SkPaint::kStroke_Style);
457
458 for (int row = 0; row < kNumQuads; ++row) {
John Stiles3b2c06c2020-06-17 12:45:57 -0400459 SkScalar x = 0;
460 SkScalar y = row * h;
461 SkPoint controlPts[] = {
462 {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY},
463 {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY},
464 {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY}
465 };
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000466
John Stiles3b2c06c2020-06-17 12:45:57 -0400467 for (int i = 0; i < 3; ++i) {
468 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
469 }
470
471 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
472
473 SkPoint chopped[5];
474 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
475
476 for (int c = 0; c < cnt; ++c) {
477 SkPoint* pts = chopped + 2 * c;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000478
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000479 for (int i = 0; i < 3; ++i) {
John Stiles3b2c06c2020-06-17 12:45:57 -0400480 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000481 }
482
John Stiles3b2c06c2020-06-17 12:45:57 -0400483 SkRect bounds;
484 bounds.setBounds(pts, 3);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000485
John Stiles3b2c06c2020-06-17 12:45:57 -0400486 canvas->drawRect(bounds, boundsPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000487
John Stiles3b2c06c2020-06-17 12:45:57 -0400488 GrPathUtils::QuadUVMatrix DevToUV(pts);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000489
Herb Derbyc76d4092020-10-07 16:46:15 -0400490 GrOp::Owner op = BezierQuadTestOp::Make(context, bounds,
491 kOpaqueBlack, DevToUV);
Brian Salomon1aa1f5f2020-12-11 17:25:17 -0500492 surfaceDrawContext->addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000493 }
494 }
495 }
496
497private:
John Stiles7571f9e2020-09-02 22:42:33 -0400498 using INHERITED = GM;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000499};
500
halcanary385fe4d2015-08-26 13:07:48 -0700501DEF_GM(return new BezierConicEffects;)
502DEF_GM(return new BezierQuadEffects;)
John Stilesa6841be2020-08-06 14:11:56 -0400503} // namespace skiagm