blob: a7f34c3b4b8bb016e351ccb5b4815dfb80b9bc8a [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"
Robert Phillipsb7bfbc22020-07-01 12:55:01 -040024#include "include/gpu/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"
Robert Phillipsce978572020-02-28 11:56:44 -050036#include "src/gpu/GrOpsRenderPass.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040037#include "src/gpu/GrPaint.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040038#include "src/gpu/GrProcessorAnalysis.h"
39#include "src/gpu/GrProcessorSet.h"
Robert Phillipsce978572020-02-28 11:56:44 -050040#include "src/gpu/GrProgramInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050041#include "src/gpu/GrRecordingContextPriv.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040042#include "src/gpu/GrRenderTargetContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050043#include "src/gpu/GrRenderTargetContextPriv.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040044#include "src/gpu/GrUserStencilSettings.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050045#include "src/gpu/effects/GrBezierEffect.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040046#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
Michael Ludwig663afe52019-06-03 16:46:19 -040047#include "src/gpu/geometry/GrPathUtils.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040048#include "src/gpu/ops/GrDrawOp.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050049#include "src/gpu/ops/GrMeshDrawOp.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040050#include "src/gpu/ops/GrOp.h"
Robert Phillips3968fcb2019-12-05 16:40:31 -050051#include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
Ben Wagner6a34f3a2019-05-01 10:59:30 -040052
53#include <memory>
54#include <utility>
55
56class GrAppliedClip;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000057
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000058namespace skiagm {
joshualitt95964c62015-02-11 13:45:50 -080059
Brian Salomon477d0ef2017-07-14 10:12:26 -040060class BezierTestOp : public GrMeshDrawOp {
61public:
62 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
63
Chris Dalton6ce447a2019-06-23 18:07:38 -060064 GrProcessorSet::Analysis finalize(
65 const GrCaps& caps, const GrAppliedClip* clip, bool hasMixedSampledCoverage,
66 GrClampType clampType) override {
Chris Daltonb8fff0d2019-03-05 10:11:58 -070067 return fProcessorSet.finalize(
68 fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
Chris Dalton6ce447a2019-06-23 18:07:38 -060069 &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, caps, clampType, &fColor);
Brian Salomon477d0ef2017-07-14 10:12:26 -040070 }
71
Chris Dalton1706cbf2019-05-21 19:35:29 -060072 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillips4f93c572020-03-18 08:13:53 -040073 if (fProgramInfo) {
74 fProgramInfo->visitFPProxies(func);
75 } else {
76 fProcessorSet.visitProxies(func);
77 }
Robert Phillipsb493eeb2017-09-13 13:10:52 -040078 }
79
Brian Salomon477d0ef2017-07-14 10:12:26 -040080protected:
John Stiles3b2c06c2020-06-17 12:45:57 -040081 BezierTestOp(const SkRect& rect, const SkPMColor4f& color, int32_t classID)
Brian Salomon477d0ef2017-07-14 10:12:26 -040082 : INHERITED(classID)
83 , fRect(rect)
84 , fColor(color)
Brian Salomon477d0ef2017-07-14 10:12:26 -040085 , fProcessorSet(SkBlendMode::kSrc) {
Greg Daniel5faf4742019-10-01 15:14:44 -040086 this->setBounds(rect, HasAABloat::kYes, IsHairline::kNo);
Brian Salomon477d0ef2017-07-14 10:12:26 -040087 }
88
Robert Phillipsce978572020-02-28 11:56:44 -050089 virtual GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) = 0;
Robert Phillips3968fcb2019-12-05 16:40:31 -050090
Robert Phillips2669a7b2020-03-12 12:07:19 -040091 GrProgramInfo* programInfo() override { return fProgramInfo; }
92
Robert Phillips4133dc42020-03-11 15:55:55 -040093 void onCreateProgramInfo(const GrCaps* caps,
94 SkArenaAlloc* arena,
Brian Salomon8afde5f2020-04-01 16:22:00 -040095 const GrSurfaceProxyView* writeView,
Robert Phillips4133dc42020-03-11 15:55:55 -040096 GrAppliedClip&& appliedClip,
97 const GrXferProcessor::DstProxyView& dstProxyView) override {
Robert Phillipsce978572020-02-28 11:56:44 -050098 auto gp = this->makeGP(*caps, arena);
99 if (!gp) {
Robert Phillips4133dc42020-03-11 15:55:55 -0400100 return;
Robert Phillipsce978572020-02-28 11:56:44 -0500101 }
102
103 GrPipeline::InputFlags flags = GrPipeline::InputFlags::kNone;
104
Brian Salomon8afde5f2020-04-01 16:22:00 -0400105 fProgramInfo = GrSimpleMeshDrawOpHelper::CreateProgramInfo(caps, arena, writeView,
Robert Phillips4133dc42020-03-11 15:55:55 -0400106 std::move(appliedClip),
107 dstProxyView, gp,
108 std::move(fProcessorSet),
109 GrPrimitiveType::kTriangles,
110 flags);
Robert Phillipsce978572020-02-28 11:56:44 -0500111 }
112
Robert Phillipsce978572020-02-28 11:56:44 -0500113 void onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) final {
114 if (!fProgramInfo) {
Robert Phillips4133dc42020-03-11 15:55:55 -0400115 this->createProgramInfo(flushState);
Robert Phillipsce978572020-02-28 11:56:44 -0500116 }
117
118 if (!fProgramInfo) {
119 return;
120 }
121
Chris Dalton765ed362020-03-16 17:34:44 -0600122 flushState->bindPipelineAndScissorClip(*fProgramInfo, chainBounds);
123 flushState->bindTextures(fProgramInfo->primProc(), nullptr, fProgramInfo->pipeline());
124 flushState->drawMesh(*fMesh);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400125 }
126
Brian Salomon477d0ef2017-07-14 10:12:26 -0400127 const SkRect& rect() const { return fRect; }
Brian Osmancf860852018-10-31 14:04:39 -0400128 const SkPMColor4f& color() const { return fColor; }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400129
Robert Phillipsce978572020-02-28 11:56:44 -0500130protected:
Chris Daltoneb694b72020-03-16 09:25:50 -0600131 GrSimpleMesh* fMesh = nullptr; // filled in by the derived classes
Robert Phillipsce978572020-02-28 11:56:44 -0500132
Brian Salomon477d0ef2017-07-14 10:12:26 -0400133private:
Robert Phillipsce978572020-02-28 11:56:44 -0500134 SkRect fRect;
135 SkPMColor4f fColor;
Robert Phillipsce978572020-02-28 11:56:44 -0500136 GrProcessorSet fProcessorSet;
137 GrProgramInfo* fProgramInfo = nullptr;
Brian Salomon477d0ef2017-07-14 10:12:26 -0400138
139 typedef GrMeshDrawOp INHERITED;
140};
141
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000142/**
143 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
144 */
Brian Salomon477d0ef2017-07-14 10:12:26 -0400145class BezierConicTestOp : public BezierTestOp {
Chris Daltonfebbffa2017-06-08 13:12:02 -0600146public:
147 DEFINE_OP_CLASS_ID
148
Robert Phillipsce978572020-02-28 11:56:44 -0500149 const char* name() const final { return "BezierConicTestOp"; }
Chris Daltonfebbffa2017-06-08 13:12:02 -0600150
Robert Phillipsbe9aff22019-02-15 11:33:22 -0500151 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Robert Phillips7c525e62018-06-12 10:11:12 -0400152 const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400153 const SkPMColor4f& color,
Robert Phillips7c525e62018-06-12 10:11:12 -0400154 const SkMatrix& klm) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500155 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400156
John Stiles3b2c06c2020-06-17 12:45:57 -0400157 return pool->allocate<BezierConicTestOp>(rect, color, klm);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600158 }
159
160private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400161 friend class ::GrOpMemoryPool; // for ctor
162
John Stiles3b2c06c2020-06-17 12:45:57 -0400163 BezierConicTestOp(const SkRect& rect, const SkPMColor4f& color, const SkMatrix& klm)
164 : INHERITED(rect, color, ClassID())
165 , fKLM(klm) {}
Brian Salomon477d0ef2017-07-14 10:12:26 -0400166
Chris Daltonfebbffa2017-06-08 13:12:02 -0600167 struct Vertex {
168 SkPoint fPosition;
169 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
170 };
171
Robert Phillipsce978572020-02-28 11:56:44 -0500172 GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) final {
John Stiles3b2c06c2020-06-17 12:45:57 -0400173 auto tmp = GrConicEffect::Make(arena, this->color(), SkMatrix::I(), caps, SkMatrix::I(),
174 false);
Robert Phillipsce978572020-02-28 11:56:44 -0500175 if (!tmp) {
176 return nullptr;
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500177 }
Robert Phillipsce978572020-02-28 11:56:44 -0500178 SkASSERT(tmp->vertexStride() == sizeof(Vertex));
179 return tmp;
180 }
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500181
Robert Phillipsce978572020-02-28 11:56:44 -0500182 void onPrepareDraws(Target* target) final {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000183 QuadHelper helper(target, sizeof(Vertex), 1);
184 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600185 if (!verts) {
186 return;
187 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400188 SkRect rect = this->rect();
Robert Phillipsce978572020-02-28 11:56:44 -0500189 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
Chris Daltonfebbffa2017-06-08 13:12:02 -0600190 for (int v = 0; v < 4; ++v) {
Cary Clarke4442cb2017-10-18 11:46:18 -0400191 SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
192 fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600193 }
Chris Dalton07cdcfc92019-02-26 11:13:22 -0700194
Robert Phillipsce978572020-02-28 11:56:44 -0500195 fMesh = helper.mesh();
Chris Daltonfebbffa2017-06-08 13:12:02 -0600196 }
197
198 SkMatrix fKLM;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600199
200 static constexpr int kVertsPerCubic = 4;
201 static constexpr int kIndicesPerCubic = 6;
202
Brian Salomon477d0ef2017-07-14 10:12:26 -0400203 typedef BezierTestOp INHERITED;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600204};
205
206
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000207/**
208 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
209 */
Chris Dalton3a778372019-02-07 15:23:36 -0700210class BezierConicEffects : public GpuGM {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000211public:
212 BezierConicEffects() {
213 this->setBGColor(0xFFFFFFFF);
214 }
215
216protected:
Robert Phillips98f3fd92019-11-21 13:16:21 -0500217 static const int kNumConics = 10;
218 static const int kCellWidth = 128;
219 static const int kCellHeight = 128;
220
mtklein36352bf2015-03-25 18:17:31 -0700221 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000222 return SkString("bezier_conic_effects");
223 }
224
mtklein36352bf2015-03-25 18:17:31 -0700225 SkISize onISize() override {
John Stiles3b2c06c2020-06-17 12:45:57 -0400226 return SkISize::Make(kCellWidth, kNumConics*kCellHeight);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000227 }
228
Robert Phillips95c250c2020-06-29 15:36:12 -0400229 void onDraw(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext,
Chris Dalton3a778372019-02-07 15:23:36 -0700230 SkCanvas* canvas) override {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500231
232 const SkScalar w = kCellWidth, h = kCellHeight;
233 const SkPMColor4f kOpaqueBlack = SkPMColor4f::FromBytes_RGBA(0xff000000);
234
235 const SkPoint baseControlPts[kNumConics][3] = {
236 { { 0.31f * w, 0.01f * h}, { 0.48f * w, 0.74f * h }, { 0.19f * w, 0.33f * h } },
237 { { 0.00f * w, 0.07f * h}, { 0.30f * w, 0.70f * h }, { 0.47f * w, 0.37f * h } },
238 { { 0.15f * w, 0.23f * h}, { 0.49f * w, 0.87f * h }, { 0.85f * w, 0.66f * h } },
239 { { 0.09f * w, 0.15f * h}, { 0.42f * w, 0.33f * h }, { 0.17f * w, 0.38f * h } },
240 { { 0.98f * w, 0.54f * h}, { 0.83f * w, 0.91f * h }, { 0.62f * w, 0.40f * h } },
241 { { 0.96f * w, 0.65f * h}, { 0.03f * w, 0.79f * h }, { 0.24f * w, 0.56f * h } },
242 { { 0.57f * w, 0.12f * h}, { 0.33f * w, 0.67f * h }, { 0.59f * w, 0.33f * h } },
243 { { 0.12f * w, 0.72f * h}, { 0.69f * w, 0.85f * h }, { 0.46f * w, 0.32f * h } },
244 { { 0.27f * w, 0.49f * h}, { 0.41f * w, 0.02f * h }, { 0.11f * w, 0.42f * h } },
245 { { 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 +0000246 };
Robert Phillips98f3fd92019-11-21 13:16:21 -0500247 const SkScalar weights[kNumConics] = { 0.62f, 0.01f, 0.95f, 1.48f, 0.37f,
248 0.66f, 0.15f, 0.14f, 0.61f, 1.4f };
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000249
Robert Phillips98f3fd92019-11-21 13:16:21 -0500250 SkPaint ctrlPtPaint;
251 ctrlPtPaint.setColor(SK_ColorRED);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000252
Robert Phillips98f3fd92019-11-21 13:16:21 -0500253 SkPaint choppedPtPaint;
254 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000255
Robert Phillips98f3fd92019-11-21 13:16:21 -0500256 SkPaint polyPaint;
257 polyPaint.setColor(0xffA0A0A0);
258 polyPaint.setStrokeWidth(0);
259 polyPaint.setStyle(SkPaint::kStroke_Style);
260
261 SkPaint boundsPaint;
262 boundsPaint.setColor(0xff808080);
263 boundsPaint.setStrokeWidth(0);
264 boundsPaint.setStyle(SkPaint::kStroke_Style);
265
266
267 for (int row = 0; row < kNumConics; ++row) {
John Stiles3b2c06c2020-06-17 12:45:57 -0400268 SkScalar x = 0;
269 SkScalar y = row * h;
270 SkPoint controlPts[] = {
271 {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY},
272 {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY},
273 {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY}
274 };
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000275
John Stiles3b2c06c2020-06-17 12:45:57 -0400276 for (int i = 0; i < 3; ++i) {
277 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
278 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000279
John Stiles3b2c06c2020-06-17 12:45:57 -0400280 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
281
282 SkConic dst[4];
283 SkMatrix klm;
284 int cnt = ChopConic(controlPts, dst, weights[row]);
285 GrPathUtils::getConicKLM(controlPts, weights[row], &klm);
286
287 for (int c = 0; c < cnt; ++c) {
288 SkPoint* pts = dst[c].fPts;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000289 for (int i = 0; i < 3; ++i) {
John Stiles3b2c06c2020-06-17 12:45:57 -0400290 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000291 }
292
John Stiles3b2c06c2020-06-17 12:45:57 -0400293 SkRect bounds;
294 bounds.setBounds(pts, 3);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000295
John Stiles3b2c06c2020-06-17 12:45:57 -0400296 canvas->drawRect(bounds, boundsPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000297
John Stiles3b2c06c2020-06-17 12:45:57 -0400298 std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(context, bounds,
299 kOpaqueBlack, klm);
300 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000301 }
302 }
303 }
304
305private:
306 // Uses the max curvature function for quads to estimate
307 // where to chop the conic. If the max curvature is not
308 // found along the curve segment it will return 1 and
309 // dst[0] is the original conic. If it returns 2 the dst[0]
310 // and dst[1] are the two new conics.
Robert Phillips98f3fd92019-11-21 13:16:21 -0500311 static int SplitConic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000312 SkScalar t = SkFindQuadMaxCurvature(src);
Chris Dalton1d474dd2018-07-24 01:08:31 -0600313 if (t == 0 || t == 1) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000314 if (dst) {
315 dst[0].set(src, weight);
316 }
317 return 1;
318 } else {
319 if (dst) {
320 SkConic conic;
321 conic.set(src, weight);
caryclark414c4292016-09-26 11:03:54 -0700322 if (!conic.chopAt(t, dst)) {
323 dst[0].set(src, weight);
324 return 1;
325 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000326 }
327 return 2;
328 }
329 }
330
Robert Phillips98f3fd92019-11-21 13:16:21 -0500331 // Calls SplitConic on the entire conic and then once more on each subsection.
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000332 // Most cases will result in either 1 conic (chop point is not within t range)
333 // or 3 points (split once and then one subsection is split again).
Robert Phillips98f3fd92019-11-21 13:16:21 -0500334 static int ChopConic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000335 SkConic dstTemp[2];
Robert Phillips98f3fd92019-11-21 13:16:21 -0500336 int conicCnt = SplitConic(src, dstTemp, weight);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000337 if (2 == conicCnt) {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500338 int conicCnt2 = SplitConic(dstTemp[0].fPts, dst, dstTemp[0].fW);
339 conicCnt = conicCnt2 + SplitConic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000340 } else {
341 dst[0] = dstTemp[0];
342 }
343 return conicCnt;
344 }
345
346 typedef GM INHERITED;
347};
348
349//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800350
Brian Salomon477d0ef2017-07-14 10:12:26 -0400351class BezierQuadTestOp : public BezierTestOp {
joshualitt95964c62015-02-11 13:45:50 -0800352public:
Brian Salomon25a88092016-12-01 09:36:50 -0500353 DEFINE_OP_CLASS_ID
Brian Salomon6b316e92016-12-16 09:35:49 -0500354 const char* name() const override { return "BezierQuadTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -0800355
Michael Ludwig28b0c5d2019-12-19 14:51:00 -0500356 static std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
Robert Phillips7c525e62018-06-12 10:11:12 -0400357 const SkRect& rect,
Brian Osmancf860852018-10-31 14:04:39 -0400358 const SkPMColor4f& color,
Robert Phillips7c525e62018-06-12 10:11:12 -0400359 const GrPathUtils::QuadUVMatrix& devToUV) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500360 GrOpMemoryPool* pool = context->priv().opMemoryPool();
Robert Phillipsc994a932018-06-19 13:09:54 -0400361
John Stiles3b2c06c2020-06-17 12:45:57 -0400362 return pool->allocate<BezierQuadTestOp>(rect, color, devToUV);
joshualitt95964c62015-02-11 13:45:50 -0800363 }
364
365private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400366 friend class ::GrOpMemoryPool; // for ctor
367
John Stiles3b2c06c2020-06-17 12:45:57 -0400368 BezierQuadTestOp(const SkRect& rect, const SkPMColor4f& color,
369 const GrPathUtils::QuadUVMatrix& devToUV)
370 : INHERITED(rect, color, ClassID())
371 , fDevToUV(devToUV) {}
joshualitt95964c62015-02-11 13:45:50 -0800372
373 struct Vertex {
374 SkPoint fPosition;
375 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
376 };
377
Robert Phillipsce978572020-02-28 11:56:44 -0500378 GrGeometryProcessor* makeGP(const GrCaps& caps, SkArenaAlloc* arena) final {
John Stiles3b2c06c2020-06-17 12:45:57 -0400379 auto tmp = GrQuadEffect::Make(arena, this->color(), SkMatrix::I(), caps, SkMatrix::I(),
380 false);
Robert Phillipsce978572020-02-28 11:56:44 -0500381 if (!tmp) {
382 return nullptr;
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500383 }
Robert Phillipsce978572020-02-28 11:56:44 -0500384 SkASSERT(tmp->vertexStride() == sizeof(Vertex));
385 return tmp;
386 }
Robert Phillips7cd0bfe2019-11-20 16:08:10 -0500387
Robert Phillipsce978572020-02-28 11:56:44 -0500388 void onPrepareDraws(Target* target) final {
Brian Salomon7eae3e02018-08-07 14:02:38 +0000389 QuadHelper helper(target, sizeof(Vertex), 1);
390 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
bsalomonb5238a72015-05-05 07:49:49 -0700391 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800392 return;
393 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400394 SkRect rect = this->rect();
Brian Salomonec42e152018-05-18 12:52:22 -0400395 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
Brian Osman568bec72018-12-26 16:48:25 -0500396 fDevToUV.apply(verts, 4, sizeof(Vertex), sizeof(SkPoint));
Robert Phillipsce978572020-02-28 11:56:44 -0500397
398 fMesh = helper.mesh();
joshualitt95964c62015-02-11 13:45:50 -0800399 }
400
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500401 GrPathUtils::QuadUVMatrix fDevToUV;
joshualitt95964c62015-02-11 13:45:50 -0800402
mtkleindbfd7ab2016-09-01 11:24:54 -0700403 static constexpr int kVertsPerCubic = 4;
404 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800405
Brian Salomon477d0ef2017-07-14 10:12:26 -0400406 typedef BezierTestOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800407};
408
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000409/**
410 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
411 */
Chris Dalton3a778372019-02-07 15:23:36 -0700412class BezierQuadEffects : public GpuGM {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000413public:
414 BezierQuadEffects() {
415 this->setBGColor(0xFFFFFFFF);
416 }
417
418protected:
Robert Phillips98f3fd92019-11-21 13:16:21 -0500419 static const int kNumQuads = 5;
420 static const int kCellWidth = 128;
421 static const int kCellHeight = 128;
422
mtklein36352bf2015-03-25 18:17:31 -0700423 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000424 return SkString("bezier_quad_effects");
425 }
426
mtklein36352bf2015-03-25 18:17:31 -0700427 SkISize onISize() override {
John Stiles3b2c06c2020-06-17 12:45:57 -0400428 return SkISize::Make(kCellWidth, kNumQuads*kCellHeight);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000429 }
430
Robert Phillips95c250c2020-06-29 15:36:12 -0400431 void onDraw(GrRecordingContext* context, GrRenderTargetContext* renderTargetContext,
Chris Dalton3a778372019-02-07 15:23:36 -0700432 SkCanvas* canvas) override {
Robert Phillips98f3fd92019-11-21 13:16:21 -0500433
434 const SkScalar w = kCellWidth, h = kCellHeight;
435 const SkPMColor4f kOpaqueBlack = SkPMColor4f::FromBytes_RGBA(0xff000000);
436
437 const SkPoint baseControlPts[kNumQuads][3] = {
438 { { 0.31f * w, 0.01f * h}, { 0.48f * w, 0.74f * h }, { 0.19f * w, 0.33f * h } },
439 { { 0.00f * w, 0.07f * h}, { 0.30f * w, 0.70f * h }, { 0.47f * w, 0.37f * h } },
440 { { 0.15f * w, 0.23f * h}, { 0.49f * w, 0.87f * h }, { 0.85f * w, 0.66f * h } },
441 { { 0.09f * w, 0.15f * h}, { 0.42f * w, 0.33f * h }, { 0.17f * w, 0.38f * h } },
442 { { 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 +0000443 };
444
Robert Phillips98f3fd92019-11-21 13:16:21 -0500445 SkPaint ctrlPtPaint;
446 ctrlPtPaint.setColor(SK_ColorRED);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000447
Robert Phillips98f3fd92019-11-21 13:16:21 -0500448 SkPaint choppedPtPaint;
449 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000450
Robert Phillips98f3fd92019-11-21 13:16:21 -0500451 SkPaint polyPaint;
452 polyPaint.setColor(0xffA0A0A0);
453 polyPaint.setStrokeWidth(0);
454 polyPaint.setStyle(SkPaint::kStroke_Style);
455
456 SkPaint boundsPaint;
457 boundsPaint.setColor(0xff808080);
458 boundsPaint.setStrokeWidth(0);
459 boundsPaint.setStyle(SkPaint::kStroke_Style);
460
461 for (int row = 0; row < kNumQuads; ++row) {
John Stiles3b2c06c2020-06-17 12:45:57 -0400462 SkScalar x = 0;
463 SkScalar y = row * h;
464 SkPoint controlPts[] = {
465 {x + baseControlPts[row][0].fX, y + baseControlPts[row][0].fY},
466 {x + baseControlPts[row][1].fX, y + baseControlPts[row][1].fY},
467 {x + baseControlPts[row][2].fX, y + baseControlPts[row][2].fY}
468 };
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000469
John Stiles3b2c06c2020-06-17 12:45:57 -0400470 for (int i = 0; i < 3; ++i) {
471 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
472 }
473
474 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
475
476 SkPoint chopped[5];
477 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
478
479 for (int c = 0; c < cnt; ++c) {
480 SkPoint* pts = chopped + 2 * c;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000481
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000482 for (int i = 0; i < 3; ++i) {
John Stiles3b2c06c2020-06-17 12:45:57 -0400483 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000484 }
485
John Stiles3b2c06c2020-06-17 12:45:57 -0400486 SkRect bounds;
487 bounds.setBounds(pts, 3);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000488
John Stiles3b2c06c2020-06-17 12:45:57 -0400489 canvas->drawRect(bounds, boundsPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000490
John Stiles3b2c06c2020-06-17 12:45:57 -0400491 GrPathUtils::QuadUVMatrix DevToUV(pts);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000492
John Stiles3b2c06c2020-06-17 12:45:57 -0400493 std::unique_ptr<GrDrawOp> op = BezierQuadTestOp::Make(context, bounds,
494 kOpaqueBlack, DevToUV);
495 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000496 }
497 }
498 }
499
500private:
501 typedef GM INHERITED;
502};
503
halcanary385fe4d2015-08-26 13:07:48 -0700504DEF_GM(return new BezierConicEffects;)
505DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000506}