blob: 016ca9ad4040f17019908bc2a8579df5b2a6ef74 [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
10#include "gm.h"
Chris Dalton1d4af542018-04-16 14:23:00 -060011#include "sk_tool_utils.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000012
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000013#include "GrContext.h"
Robert Phillips7c525e62018-06-12 10:11:12 -040014#include "GrMemoryPool.h"
Brian Salomon477d0ef2017-07-14 10:12:26 -040015#include "GrOpFlushState.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000016#include "GrPathUtils.h"
Brian Salomon477d0ef2017-07-14 10:12:26 -040017#include "GrRenderTargetContextPriv.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000018#include "GrTest.h"
19#include "SkColorPriv.h"
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000020#include "SkGeometry.h"
Cary Clarke4442cb2017-10-18 11:46:18 -040021#include "SkPoint3.h"
Cary Clark74f623d2017-11-06 20:02:02 -050022#include "SkPointPriv.h"
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000023#include "effects/GrBezierEffect.h"
Brian Salomon477d0ef2017-07-14 10:12:26 -040024#include "ops/GrMeshDrawOp.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000025
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000026namespace skiagm {
joshualitt95964c62015-02-11 13:45:50 -080027
Brian Salomon477d0ef2017-07-14 10:12:26 -040028class BezierTestOp : public GrMeshDrawOp {
29public:
30 FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
31
Brian Osman532b3f92018-07-11 10:02:07 -040032 RequiresDstTexture finalize(const GrCaps& caps, const GrAppliedClip* clip) override {
Brian Salomon477d0ef2017-07-14 10:12:26 -040033 auto analysis = fProcessorSet.finalize(fColor, GrProcessorAnalysisCoverage::kSingleChannel,
Brian Osman532b3f92018-07-11 10:02:07 -040034 clip, false, caps, &fColor);
Brian Salomon477d0ef2017-07-14 10:12:26 -040035 return analysis.requiresDstTexture() ? RequiresDstTexture::kYes : RequiresDstTexture::kNo;
36 }
37
Robert Phillipsf1748f52017-09-14 14:11:24 -040038 void visitProxies(const VisitProxyFunc& func) const override {
Robert Phillipsb493eeb2017-09-13 13:10:52 -040039 fProcessorSet.visitProxies(func);
40 }
41
Brian Salomon477d0ef2017-07-14 10:12:26 -040042protected:
Brian Salomon7eae3e02018-08-07 14:02:38 +000043 BezierTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
44 int32_t classID)
Brian Salomon477d0ef2017-07-14 10:12:26 -040045 : INHERITED(classID)
46 , fRect(rect)
47 , fColor(color)
48 , fGeometryProcessor(std::move(gp))
49 , fProcessorSet(SkBlendMode::kSrc) {
50 this->setBounds(rect, HasAABloat::kYes, IsZeroArea::kNo);
51 }
52
Brian Salomon49348902018-06-26 09:12:38 -040053 Target::PipelineAndFixedDynamicState makePipeline(Target* target) {
Brian Salomonbfd18cd2017-08-09 16:27:09 -040054 return target->makePipeline(0, std::move(fProcessorSet), target->detachAppliedClip());
Brian Salomon477d0ef2017-07-14 10:12:26 -040055 }
56
Brian Salomon7eae3e02018-08-07 14:02:38 +000057 sk_sp<const GrGeometryProcessor> gp() const { return fGeometryProcessor; }
Brian Salomon477d0ef2017-07-14 10:12:26 -040058
59 const SkRect& rect() const { return fRect; }
60 GrColor color() const { return fColor; }
61
62private:
Brian Salomon477d0ef2017-07-14 10:12:26 -040063 SkRect fRect;
64 GrColor fColor;
Brian Salomon7eae3e02018-08-07 14:02:38 +000065 sk_sp<const GrGeometryProcessor> fGeometryProcessor;
Brian Salomon477d0ef2017-07-14 10:12:26 -040066 GrProcessorSet fProcessorSet;
67
68 typedef GrMeshDrawOp INHERITED;
69};
70
71class BezierCubicTestOp : public BezierTestOp {
joshualitt95964c62015-02-11 13:45:50 -080072public:
Brian Salomon25a88092016-12-01 09:36:50 -050073 DEFINE_OP_CLASS_ID
joshualitt95964c62015-02-11 13:45:50 -080074
Chris Daltonfebbffa2017-06-08 13:12:02 -060075 const char* name() const override { return "BezierCubicTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -080076
Robert Phillips7c525e62018-06-12 10:11:12 -040077 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
Brian Salomon7eae3e02018-08-07 14:02:38 +000078 sk_sp<const GrGeometryProcessor> gp,
Robert Phillips7c525e62018-06-12 10:11:12 -040079 const SkRect& rect,
Brian Salomon477d0ef2017-07-14 10:12:26 -040080 GrColor color) {
Robert Phillipsc994a932018-06-19 13:09:54 -040081 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
82
83 return pool->allocate<BezierCubicTestOp>(std::move(gp), rect, color);
Brian Salomon6b316e92016-12-16 09:35:49 -050084 }
85
86private:
Robert Phillips7c525e62018-06-12 10:11:12 -040087 friend class ::GrOpMemoryPool; // for ctor
88
Brian Salomon7eae3e02018-08-07 14:02:38 +000089 BezierCubicTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color)
Brian Salomon477d0ef2017-07-14 10:12:26 -040090 : INHERITED(std::move(gp), rect, color, ClassID()) {}
joshualitt95964c62015-02-11 13:45:50 -080091
Brian Salomon91326c32017-08-09 16:02:19 -040092 void onPrepareDraws(Target* target) override {
Brian Salomon92be2f72018-06-19 14:33:47 -040093 SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(SkPoint));
Brian Salomon7eae3e02018-08-07 14:02:38 +000094 QuadHelper helper(target, sizeof(SkPoint), 1);
95 SkPoint* pts = reinterpret_cast<SkPoint*>(helper.vertices());
Chris Daltonfebbffa2017-06-08 13:12:02 -060096 if (!pts) {
joshualitt4b31de82015-03-05 14:33:41 -080097 return;
98 }
Brian Salomon477d0ef2017-07-14 10:12:26 -040099 SkRect rect = this->rect();
Brian Salomon92be2f72018-06-19 14:33:47 -0400100 SkPointPriv::SetRectTriStrip(pts, rect, sizeof(SkPoint));
Brian Salomon49348902018-06-26 09:12:38 -0400101 auto pipe = this->makePipeline(target);
102 helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState);
joshualitt95964c62015-02-11 13:45:50 -0800103 }
104
mtkleindbfd7ab2016-09-01 11:24:54 -0700105 static constexpr int kVertsPerCubic = 4;
106 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800107
Brian Salomon477d0ef2017-07-14 10:12:26 -0400108 typedef BezierTestOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800109};
110
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000111/**
112 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
113 */
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000114class BezierCubicEffects : public GM {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000115public:
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000116 BezierCubicEffects() {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000117 this->setBGColor(0xFFFFFFFF);
118 }
119
120protected:
mtklein36352bf2015-03-25 18:17:31 -0700121 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000122 return SkString("bezier_cubic_effects");
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000123 }
124
mtklein36352bf2015-03-25 18:17:31 -0700125 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700126 return SkISize::Make(800, 800);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000127 }
128
mtklein36352bf2015-03-25 18:17:31 -0700129 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400130 GrRenderTargetContext* renderTargetContext =
131 canvas->internal_private_accessTopLayerRenderTargetContext();
132 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700133 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000134 return;
135 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000136
robertphillips175dd9b2016-04-28 14:32:04 -0700137 GrContext* context = canvas->getGrContext();
138 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800139 return;
140 }
141
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400142 if (!context->contextPriv().caps()->shaderCaps()->floatIs32Bits()) {
Chris Dalton1d4af542018-04-16 14:23:00 -0600143 SkPaint paint;
144 sk_tool_utils::set_portable_typeface(&paint);
145 paint.setAntiAlias(true);
146 paint.setTextSize(20);
147
148 canvas->clear(SK_ColorWHITE);
149 canvas->drawString("float != fp32", 20, 40, paint);
150 return;
151 }
152
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000153 struct Vertex {
154 SkPoint fPosition;
155 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
156 };
157
mtkleindbfd7ab2016-09-01 11:24:54 -0700158 constexpr int kNumCubics = 15;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000159 SkRandom rand;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000160
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000161 // Mult by 3 for each edge effect type
162 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
163 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400164 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
165 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000166 int row = 0;
167 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700168 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000169
170 for (int i = 0; i < kNumCubics; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000171 SkPoint baseControlPts[] = {
172 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
173 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
174 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
175 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000176 };
Ethan Nicholas1706f842017-11-10 11:58:19 -0500177 for(GrClipEdgeType edgeType : {GrClipEdgeType::kFillBW,
178 GrClipEdgeType::kFillAA,
179 GrClipEdgeType::kHairlineAA}) {
Mike Reeddf85c382017-02-14 10:59:19 -0500180 SkScalar x = col * w;
181 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000182 SkPoint controlPts[] = {
183 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
184 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
185 {x + baseControlPts[2].fX, y + baseControlPts[2].fY},
186 {x + baseControlPts[3].fX, y + baseControlPts[3].fY}
187 };
188 SkPoint chopped[10];
csmartdaltoncc261272017-03-23 13:38:45 -0600189 SkMatrix klm;
Greg Daniel8199d942017-03-14 10:20:24 -0400190 int loopIndex;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000191 int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
192 chopped,
csmartdaltoncc261272017-03-23 13:38:45 -0600193 &klm,
Greg Daniel8199d942017-03-14 10:20:24 -0400194 &loopIndex);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000195
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000196 SkPaint ctrlPtPaint;
197 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
Hal Canary23e474c2017-05-15 13:35:35 -0400198 canvas->drawCircle(controlPts[0], 8.f, ctrlPtPaint);
Greg Daniel8199d942017-03-14 10:20:24 -0400199 for (int i = 1; i < 4; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400200 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000201 }
202
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000203 SkPaint polyPaint;
204 polyPaint.setColor(0xffA0A0A0);
205 polyPaint.setStrokeWidth(0);
206 polyPaint.setStyle(SkPaint::kStroke_Style);
207 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000208
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000209 SkPaint choppedPtPaint;
210 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000211
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000212 for (int c = 0; c < cnt; ++c) {
213 SkPoint* pts = chopped + 3 * c;
214
215 for (int i = 0; i < 4; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400216 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000217 }
218
219 SkRect bounds;
220 bounds.set(pts, 4);
221
222 SkPaint boundsPaint;
223 boundsPaint.setColor(0xff808080);
224 boundsPaint.setStrokeWidth(0);
225 boundsPaint.setStyle(SkPaint::kStroke_Style);
226 canvas->drawRect(bounds, boundsPaint);
227
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000228
Chris Daltonfebbffa2017-06-08 13:12:02 -0600229 bool flipKL = (c == loopIndex && cnt != 3);
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400230 sk_sp<GrGeometryProcessor> gp =
231 GrCubicEffect::Make(color, SkMatrix::I(), klm, flipKL, edgeType,
232 *context->contextPriv().caps());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600233 if (!gp) {
234 break;
Greg Daniel8199d942017-03-14 10:20:24 -0400235 }
236
Brian Salomon477d0ef2017-07-14 10:12:26 -0400237 std::unique_ptr<GrDrawOp> op =
Robert Phillips7c525e62018-06-12 10:11:12 -0400238 BezierCubicTestOp::Make(context, std::move(gp), bounds, color);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400239 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000240 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000241 ++col;
242 if (numCols == col) {
243 col = 0;
244 ++row;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000245 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000246 }
247 }
248 }
249
250private:
251 typedef GM INHERITED;
252};
253
254//////////////////////////////////////////////////////////////////////////////
255
Brian Salomon477d0ef2017-07-14 10:12:26 -0400256class BezierConicTestOp : public BezierTestOp {
Chris Daltonfebbffa2017-06-08 13:12:02 -0600257public:
258 DEFINE_OP_CLASS_ID
259
260 const char* name() const override { return "BezierConicTestOp"; }
261
Robert Phillips7c525e62018-06-12 10:11:12 -0400262 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
Brian Salomon7eae3e02018-08-07 14:02:38 +0000263 sk_sp<const GrGeometryProcessor> gp,
Robert Phillips7c525e62018-06-12 10:11:12 -0400264 const SkRect& rect,
265 GrColor color,
266 const SkMatrix& klm) {
Robert Phillipsc994a932018-06-19 13:09:54 -0400267 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
268
269 return pool->allocate<BezierConicTestOp>(std::move(gp), rect, color, klm);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600270 }
271
272private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400273 friend class ::GrOpMemoryPool; // for ctor
274
Brian Salomon7eae3e02018-08-07 14:02:38 +0000275 BezierConicTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
Chris Daltonfebbffa2017-06-08 13:12:02 -0600276 const SkMatrix& klm)
Brian Salomon477d0ef2017-07-14 10:12:26 -0400277 : INHERITED(std::move(gp), rect, color, ClassID()), fKLM(klm) {}
278
Chris Daltonfebbffa2017-06-08 13:12:02 -0600279 struct Vertex {
280 SkPoint fPosition;
281 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
282 };
283
Brian Salomon91326c32017-08-09 16:02:19 -0400284 void onPrepareDraws(Target* target) override {
Brian Salomon92be2f72018-06-19 14:33:47 -0400285 SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(Vertex));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000286 QuadHelper helper(target, sizeof(Vertex), 1);
287 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
Chris Daltonfebbffa2017-06-08 13:12:02 -0600288 if (!verts) {
289 return;
290 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400291 SkRect rect = this->rect();
Cary Clark74f623d2017-11-06 20:02:02 -0500292 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect.fLeft, rect.fTop, rect.fRight,
293 rect.fBottom, sizeof(Vertex));
Chris Daltonfebbffa2017-06-08 13:12:02 -0600294 for (int v = 0; v < 4; ++v) {
Cary Clarke4442cb2017-10-18 11:46:18 -0400295 SkPoint3 pt3 = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
296 fKLM.mapHomogeneousPoints((SkPoint3* ) verts[v].fKLM, &pt3, 1);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600297 }
Brian Salomon49348902018-06-26 09:12:38 -0400298 auto pipe = this->makePipeline(target);
299 helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState);
Chris Daltonfebbffa2017-06-08 13:12:02 -0600300 }
301
302 SkMatrix fKLM;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600303
304 static constexpr int kVertsPerCubic = 4;
305 static constexpr int kIndicesPerCubic = 6;
306
Brian Salomon477d0ef2017-07-14 10:12:26 -0400307 typedef BezierTestOp INHERITED;
Chris Daltonfebbffa2017-06-08 13:12:02 -0600308};
309
310
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000311/**
312 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
313 */
314class BezierConicEffects : public GM {
315public:
316 BezierConicEffects() {
317 this->setBGColor(0xFFFFFFFF);
318 }
319
320protected:
mtklein36352bf2015-03-25 18:17:31 -0700321 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000322 return SkString("bezier_conic_effects");
323 }
324
mtklein36352bf2015-03-25 18:17:31 -0700325 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700326 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000327 }
328
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000329
mtklein36352bf2015-03-25 18:17:31 -0700330 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400331 GrRenderTargetContext* renderTargetContext =
332 canvas->internal_private_accessTopLayerRenderTargetContext();
333 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700334 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000335 return;
336 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000337
robertphillips175dd9b2016-04-28 14:32:04 -0700338 GrContext* context = canvas->getGrContext();
339 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800340 return;
341 }
342
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000343 struct Vertex {
344 SkPoint fPosition;
345 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
346 };
347
mtkleindbfd7ab2016-09-01 11:24:54 -0700348 constexpr int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000349 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000350
351 // Mult by 3 for each edge effect type
352 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
353 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400354 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
355 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000356 int row = 0;
357 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700358 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000359
360 for (int i = 0; i < kNumConics; ++i) {
361 SkPoint baseControlPts[] = {
362 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
363 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
364 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
365 };
366 SkScalar weight = rand.nextRangeF(0.f, 2.f);
Ethan Nicholas1706f842017-11-10 11:58:19 -0500367 for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700368 sk_sp<GrGeometryProcessor> gp;
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500369 GrClipEdgeType et = (GrClipEdgeType)edgeType;
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400370 gp = GrConicEffect::Make(color, SkMatrix::I(), et, *context->contextPriv().caps(),
371 SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800372 if (!gp) {
373 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000374 }
375
Mike Reeddf85c382017-02-14 10:59:19 -0500376 SkScalar x = col * w;
377 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000378 SkPoint controlPts[] = {
379 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
380 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
381 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
382 };
383 SkConic dst[4];
csmartdaltoncc261272017-03-23 13:38:45 -0600384 SkMatrix klm;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000385 int cnt = chop_conic(controlPts, dst, weight);
csmartdaltoncc261272017-03-23 13:38:45 -0600386 GrPathUtils::getConicKLM(controlPts, weight, &klm);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000387
388 SkPaint ctrlPtPaint;
389 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
390 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400391 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000392 }
393
394 SkPaint polyPaint;
395 polyPaint.setColor(0xffA0A0A0);
396 polyPaint.setStrokeWidth(0);
397 polyPaint.setStyle(SkPaint::kStroke_Style);
398 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
399
400 SkPaint choppedPtPaint;
401 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
402
403 for (int c = 0; c < cnt; ++c) {
404 SkPoint* pts = dst[c].fPts;
405 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400406 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000407 }
408
409 SkRect bounds;
410 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
411 //bounds.set(bPts, 2);
412 bounds.set(pts, 3);
413
414 SkPaint boundsPaint;
415 boundsPaint.setColor(0xff808080);
416 boundsPaint.setStrokeWidth(0);
417 boundsPaint.setStyle(SkPaint::kStroke_Style);
418 canvas->drawRect(bounds, boundsPaint);
419
Robert Phillips7c525e62018-06-12 10:11:12 -0400420 std::unique_ptr<GrDrawOp> op = BezierConicTestOp::Make(context, gp, bounds,
421 color, klm);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400422 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000423 }
424 ++col;
425 if (numCols == col) {
426 col = 0;
427 ++row;
428 }
429 }
430 }
431 }
432
433private:
434 // Uses the max curvature function for quads to estimate
435 // where to chop the conic. If the max curvature is not
436 // found along the curve segment it will return 1 and
437 // dst[0] is the original conic. If it returns 2 the dst[0]
438 // and dst[1] are the two new conics.
439 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
440 SkScalar t = SkFindQuadMaxCurvature(src);
Chris Dalton1d474dd2018-07-24 01:08:31 -0600441 if (t == 0 || t == 1) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000442 if (dst) {
443 dst[0].set(src, weight);
444 }
445 return 1;
446 } else {
447 if (dst) {
448 SkConic conic;
449 conic.set(src, weight);
caryclark414c4292016-09-26 11:03:54 -0700450 if (!conic.chopAt(t, dst)) {
451 dst[0].set(src, weight);
452 return 1;
453 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000454 }
455 return 2;
456 }
457 }
458
459 // Calls split_conic on the entire conic and then once more on each subsection.
460 // Most cases will result in either 1 conic (chop point is not within t range)
461 // or 3 points (split once and then one subsection is split again).
462 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
463 SkConic dstTemp[2];
464 int conicCnt = split_conic(src, dstTemp, weight);
465 if (2 == conicCnt) {
466 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
467 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
468 } else {
469 dst[0] = dstTemp[0];
470 }
471 return conicCnt;
472 }
473
474 typedef GM INHERITED;
475};
476
477//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800478
Brian Salomon477d0ef2017-07-14 10:12:26 -0400479class BezierQuadTestOp : public BezierTestOp {
joshualitt95964c62015-02-11 13:45:50 -0800480public:
Brian Salomon25a88092016-12-01 09:36:50 -0500481 DEFINE_OP_CLASS_ID
Brian Salomon6b316e92016-12-16 09:35:49 -0500482 const char* name() const override { return "BezierQuadTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -0800483
Robert Phillips7c525e62018-06-12 10:11:12 -0400484 static std::unique_ptr<GrDrawOp> Make(GrContext* context,
Brian Salomon7eae3e02018-08-07 14:02:38 +0000485 sk_sp<const GrGeometryProcessor> gp,
Robert Phillips7c525e62018-06-12 10:11:12 -0400486 const SkRect& rect,
487 GrColor color,
488 const GrPathUtils::QuadUVMatrix& devToUV) {
Robert Phillipsc994a932018-06-19 13:09:54 -0400489 GrOpMemoryPool* pool = context->contextPriv().opMemoryPool();
490
491 return pool->allocate<BezierQuadTestOp>(std::move(gp), rect, color, devToUV);
joshualitt95964c62015-02-11 13:45:50 -0800492 }
493
494private:
Robert Phillips7c525e62018-06-12 10:11:12 -0400495 friend class ::GrOpMemoryPool; // for ctor
496
Brian Salomon7eae3e02018-08-07 14:02:38 +0000497 BezierQuadTestOp(sk_sp<const GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
Brian Salomon6b316e92016-12-16 09:35:49 -0500498 const GrPathUtils::QuadUVMatrix& devToUV)
Brian Salomon477d0ef2017-07-14 10:12:26 -0400499 : INHERITED(std::move(gp), rect, color, ClassID()), fDevToUV(devToUV) {}
joshualitt95964c62015-02-11 13:45:50 -0800500
501 struct Vertex {
502 SkPoint fPosition;
503 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
504 };
505
Brian Salomon91326c32017-08-09 16:02:19 -0400506 void onPrepareDraws(Target* target) override {
Brian Salomon92be2f72018-06-19 14:33:47 -0400507 SkASSERT(this->gp()->debugOnly_vertexStride() == sizeof(Vertex));
Brian Salomon7eae3e02018-08-07 14:02:38 +0000508 QuadHelper helper(target, sizeof(Vertex), 1);
509 Vertex* verts = reinterpret_cast<Vertex*>(helper.vertices());
bsalomonb5238a72015-05-05 07:49:49 -0700510 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800511 return;
512 }
Brian Salomon477d0ef2017-07-14 10:12:26 -0400513 SkRect rect = this->rect();
Brian Salomonec42e152018-05-18 12:52:22 -0400514 SkPointPriv::SetRectTriStrip(&verts[0].fPosition, rect, sizeof(Vertex));
joshualitt95964c62015-02-11 13:45:50 -0800515 fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
Brian Salomon49348902018-06-26 09:12:38 -0400516 auto pipe = this->makePipeline(target);
517 helper.recordDraw(target, this->gp(), pipe.fPipeline, pipe.fFixedDynamicState);
joshualitt95964c62015-02-11 13:45:50 -0800518 }
519
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500520 GrPathUtils::QuadUVMatrix fDevToUV;
joshualitt95964c62015-02-11 13:45:50 -0800521
mtkleindbfd7ab2016-09-01 11:24:54 -0700522 static constexpr int kVertsPerCubic = 4;
523 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800524
Brian Salomon477d0ef2017-07-14 10:12:26 -0400525 typedef BezierTestOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800526};
527
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000528/**
529 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
530 */
531class BezierQuadEffects : public GM {
532public:
533 BezierQuadEffects() {
534 this->setBGColor(0xFFFFFFFF);
535 }
536
537protected:
mtklein36352bf2015-03-25 18:17:31 -0700538 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000539 return SkString("bezier_quad_effects");
540 }
541
mtklein36352bf2015-03-25 18:17:31 -0700542 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700543 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000544 }
545
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000546
mtklein36352bf2015-03-25 18:17:31 -0700547 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400548 GrRenderTargetContext* renderTargetContext =
549 canvas->internal_private_accessTopLayerRenderTargetContext();
550 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700551 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000552 return;
553 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000554
robertphillips175dd9b2016-04-28 14:32:04 -0700555 GrContext* context = canvas->getGrContext();
556 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800557 return;
558 }
559
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000560 struct Vertex {
561 SkPoint fPosition;
562 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
563 };
564
mtkleindbfd7ab2016-09-01 11:24:54 -0700565 constexpr int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000566 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000567
568 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
569 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400570 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
571 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000572 int row = 0;
573 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700574 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000575
576 for (int i = 0; i < kNumQuads; ++i) {
577 SkPoint baseControlPts[] = {
578 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
579 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
580 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
581 };
Ethan Nicholas1706f842017-11-10 11:58:19 -0500582 for(int edgeType = 0; edgeType < kGrClipEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700583 sk_sp<GrGeometryProcessor> gp;
Ethan Nicholas0f3c7322017-11-09 14:51:17 -0500584 GrClipEdgeType et = (GrClipEdgeType)edgeType;
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400585 gp = GrQuadEffect::Make(color, SkMatrix::I(), et, *context->contextPriv().caps(),
586 SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800587 if (!gp) {
588 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000589 }
590
Mike Reeddf85c382017-02-14 10:59:19 -0500591 SkScalar x = col * w;
592 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000593 SkPoint controlPts[] = {
594 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
595 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
596 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
597 };
598 SkPoint chopped[5];
599 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
600
601 SkPaint ctrlPtPaint;
602 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
603 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400604 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000605 }
606
607 SkPaint polyPaint;
608 polyPaint.setColor(0xffA0A0A0);
609 polyPaint.setStrokeWidth(0);
610 polyPaint.setStyle(SkPaint::kStroke_Style);
611 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
612
613 SkPaint choppedPtPaint;
614 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
615
616 for (int c = 0; c < cnt; ++c) {
617 SkPoint* pts = chopped + 2 * c;
618
619 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400620 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000621 }
622
623 SkRect bounds;
624 bounds.set(pts, 3);
625
626 SkPaint boundsPaint;
627 boundsPaint.setColor(0xff808080);
628 boundsPaint.setStrokeWidth(0);
629 boundsPaint.setStyle(SkPaint::kStroke_Style);
630 canvas->drawRect(bounds, boundsPaint);
631
robertphillips28a838e2016-06-23 14:07:00 -0700632 GrPaint grPaint;
Brian Salomona1633922017-01-09 11:46:10 -0500633 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
joshualitt3f284d72015-02-11 11:34:58 -0800634
joshualitt95964c62015-02-11 13:45:50 -0800635 GrPathUtils::QuadUVMatrix DevToUV(pts);
636
Robert Phillips7c525e62018-06-12 10:11:12 -0400637 std::unique_ptr<GrDrawOp> op = BezierQuadTestOp::Make(context, gp,
638 bounds, color, DevToUV);
Brian Salomon477d0ef2017-07-14 10:12:26 -0400639 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000640 }
641 ++col;
642 if (numCols == col) {
643 col = 0;
644 ++row;
645 }
646 }
647 }
648 }
649
650private:
651 typedef GM INHERITED;
652};
653
halcanary385fe4d2015-08-26 13:07:48 -0700654DEF_GM(return new BezierCubicEffects;)
655DEF_GM(return new BezierConicEffects;)
656DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000657}