blob: 7e492b0ca2e25cdb90d1c6a83a6c329630f049bb [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"
11
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000012#if SK_SUPPORT_GPU
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000013
Brian Osman11052242016-10-27 14:47:55 -040014#include "GrRenderTargetContextPriv.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000015#include "GrContext.h"
16#include "GrPathUtils.h"
17#include "GrTest.h"
18#include "SkColorPriv.h"
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000019#include "SkGeometry.h"
20
Brian Salomon89527432016-12-16 09:52:16 -050021#include "ops/GrTestMeshDrawOp.h"
joshualitt2771b562015-08-07 12:46:26 -070022
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000023#include "effects/GrBezierEffect.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000024
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000025namespace skiagm {
joshualitt95964c62015-02-11 13:45:50 -080026
Chris Daltonfebbffa2017-06-08 13:12:02 -060027class BezierCubicTestOp : public GrTestMeshDrawOp {
joshualitt95964c62015-02-11 13:45:50 -080028public:
Brian Salomon25a88092016-12-01 09:36:50 -050029 DEFINE_OP_CLASS_ID
joshualitt95964c62015-02-11 13:45:50 -080030
Chris Daltonfebbffa2017-06-08 13:12:02 -060031 const char* name() const override { return "BezierCubicTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -080032
Brian Salomond3ccb0a2017-04-03 10:38:00 -040033 static std::unique_ptr<GrLegacyMeshDrawOp> Make(sk_sp<GrGeometryProcessor> gp,
Chris Daltonfebbffa2017-06-08 13:12:02 -060034 const SkRect& rect, GrColor color) {
35 return std::unique_ptr<GrLegacyMeshDrawOp>(new BezierCubicTestOp(gp, rect, color));
Brian Salomon6b316e92016-12-16 09:35:49 -050036 }
37
38private:
Chris Daltonfebbffa2017-06-08 13:12:02 -060039 BezierCubicTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color)
csmartdaltoncc261272017-03-23 13:38:45 -060040 : INHERITED(ClassID(), rect, color)
csmartdaltoncc261272017-03-23 13:38:45 -060041 , fRect(rect)
42 , fGeometryProcessor(std::move(gp)) {
joshualitt95964c62015-02-11 13:45:50 -080043 }
joshualitt95964c62015-02-11 13:45:50 -080044
bsalomon342bfc22016-04-01 06:06:20 -070045 void onPrepareDraws(Target* target) const override {
bsalomonb5238a72015-05-05 07:49:49 -070046 QuadHelper helper;
bsalomon342bfc22016-04-01 06:06:20 -070047 size_t vertexStride = fGeometryProcessor->getVertexStride();
Chris Daltonfebbffa2017-06-08 13:12:02 -060048 SkASSERT(vertexStride == sizeof(SkPoint));
49 SkPoint* pts = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1));
50 if (!pts) {
joshualitt4b31de82015-03-05 14:33:41 -080051 return;
52 }
Chris Daltonfebbffa2017-06-08 13:12:02 -060053 pts[0].setRectFan(fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom, vertexStride);
Brian Salomond3ccb0a2017-04-03 10:38:00 -040054 helper.recordDraw(target, fGeometryProcessor.get(), this->pipeline());
joshualitt95964c62015-02-11 13:45:50 -080055 }
56
Brian Salomon9e50f7b2017-03-06 12:02:34 -050057 SkRect fRect;
bungeman06ca8ec2016-06-09 08:01:03 -070058 sk_sp<GrGeometryProcessor> fGeometryProcessor;
joshualitt95964c62015-02-11 13:45:50 -080059
mtkleindbfd7ab2016-09-01 11:24:54 -070060 static constexpr int kVertsPerCubic = 4;
61 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -080062
Brian Salomon6b316e92016-12-16 09:35:49 -050063 typedef GrTestMeshDrawOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -080064};
65
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000066/**
67 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
68 */
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000069class BezierCubicEffects : public GM {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000070public:
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000071 BezierCubicEffects() {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000072 this->setBGColor(0xFFFFFFFF);
73 }
74
75protected:
mtklein36352bf2015-03-25 18:17:31 -070076 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000077 return SkString("bezier_cubic_effects");
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000078 }
79
mtklein36352bf2015-03-25 18:17:31 -070080 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -070081 return SkISize::Make(800, 800);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000082 }
83
mtklein36352bf2015-03-25 18:17:31 -070084 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -040085 GrRenderTargetContext* renderTargetContext =
86 canvas->internal_private_accessTopLayerRenderTargetContext();
87 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -070088 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000089 return;
90 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000091
robertphillips175dd9b2016-04-28 14:32:04 -070092 GrContext* context = canvas->getGrContext();
93 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -080094 return;
95 }
96
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000097 struct Vertex {
98 SkPoint fPosition;
99 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
100 };
101
mtkleindbfd7ab2016-09-01 11:24:54 -0700102 constexpr int kNumCubics = 15;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000103 SkRandom rand;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000104
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000105 // Mult by 3 for each edge effect type
106 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
107 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400108 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
109 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000110 int row = 0;
111 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700112 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000113
114 for (int i = 0; i < kNumCubics; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000115 SkPoint baseControlPts[] = {
116 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
117 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
118 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
119 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000120 };
Chris Daltonfebbffa2017-06-08 13:12:02 -0600121 for(GrPrimitiveEdgeType edgeType : {kFillBW_GrProcessorEdgeType,
122 kFillAA_GrProcessorEdgeType,
123 kHairlineAA_GrProcessorEdgeType}) {
Mike Reeddf85c382017-02-14 10:59:19 -0500124 SkScalar x = col * w;
125 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000126 SkPoint controlPts[] = {
127 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
128 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
129 {x + baseControlPts[2].fX, y + baseControlPts[2].fY},
130 {x + baseControlPts[3].fX, y + baseControlPts[3].fY}
131 };
132 SkPoint chopped[10];
csmartdaltoncc261272017-03-23 13:38:45 -0600133 SkMatrix klm;
Greg Daniel8199d942017-03-14 10:20:24 -0400134 int loopIndex;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000135 int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
136 chopped,
csmartdaltoncc261272017-03-23 13:38:45 -0600137 &klm,
Greg Daniel8199d942017-03-14 10:20:24 -0400138 &loopIndex);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000139
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000140 SkPaint ctrlPtPaint;
141 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
Hal Canary23e474c2017-05-15 13:35:35 -0400142 canvas->drawCircle(controlPts[0], 8.f, ctrlPtPaint);
Greg Daniel8199d942017-03-14 10:20:24 -0400143 for (int i = 1; i < 4; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400144 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000145 }
146
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000147 SkPaint polyPaint;
148 polyPaint.setColor(0xffA0A0A0);
149 polyPaint.setStrokeWidth(0);
150 polyPaint.setStyle(SkPaint::kStroke_Style);
151 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000152
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000153 SkPaint choppedPtPaint;
154 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000155
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000156 for (int c = 0; c < cnt; ++c) {
157 SkPoint* pts = chopped + 3 * c;
158
159 for (int i = 0; i < 4; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400160 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000161 }
162
163 SkRect bounds;
164 bounds.set(pts, 4);
165
166 SkPaint boundsPaint;
167 boundsPaint.setColor(0xff808080);
168 boundsPaint.setStrokeWidth(0);
169 boundsPaint.setStyle(SkPaint::kStroke_Style);
170 canvas->drawRect(bounds, boundsPaint);
171
robertphillips28a838e2016-06-23 14:07:00 -0700172 GrPaint grPaint;
Brian Salomona1633922017-01-09 11:46:10 -0500173 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000174
Chris Daltonfebbffa2017-06-08 13:12:02 -0600175 bool flipKL = (c == loopIndex && cnt != 3);
176 sk_sp<GrGeometryProcessor> gp = GrCubicEffect::Make(color, SkMatrix::I(), klm,
177 flipKL, edgeType,
178 *context->caps());
179 if (!gp) {
180 break;
Greg Daniel8199d942017-03-14 10:20:24 -0400181 }
182
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400183 std::unique_ptr<GrLegacyMeshDrawOp> op =
Chris Daltonfebbffa2017-06-08 13:12:02 -0600184 BezierCubicTestOp::Make(std::move(gp), bounds, color);
joshualitt95964c62015-02-11 13:45:50 -0800185
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400186 renderTargetContext->priv().testingOnly_addLegacyMeshDrawOp(
Brian Salomon82f44312017-01-11 13:42:54 -0500187 std::move(grPaint), GrAAType::kNone, std::move(op));
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000188 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000189 ++col;
190 if (numCols == col) {
191 col = 0;
192 ++row;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000193 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000194 }
195 }
196 }
197
198private:
199 typedef GM INHERITED;
200};
201
202//////////////////////////////////////////////////////////////////////////////
203
Chris Daltonfebbffa2017-06-08 13:12:02 -0600204class BezierConicTestOp : public GrTestMeshDrawOp {
205public:
206 DEFINE_OP_CLASS_ID
207
208 const char* name() const override { return "BezierConicTestOp"; }
209
210 static std::unique_ptr<GrLegacyMeshDrawOp> Make(sk_sp<GrGeometryProcessor> gp,
211 const SkRect& rect, GrColor color,
212 const SkMatrix& klm) {
213 return std::unique_ptr<GrLegacyMeshDrawOp>(new BezierConicTestOp(gp, rect, color, klm));
214 }
215
216private:
217 BezierConicTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
218 const SkMatrix& klm)
219 : INHERITED(ClassID(), rect, color)
220 , fKLM(klm)
221 , fRect(rect)
222 , fGeometryProcessor(std::move(gp)) {
223 }
224 struct Vertex {
225 SkPoint fPosition;
226 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
227 };
228
229 void onPrepareDraws(Target* target) const override {
230 QuadHelper helper;
231 size_t vertexStride = fGeometryProcessor->getVertexStride();
232 SkASSERT(vertexStride == sizeof(Vertex));
233 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
234 if (!verts) {
235 return;
236 }
237 verts[0].fPosition.setRectFan(fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom,
238 sizeof(Vertex));
239 for (int v = 0; v < 4; ++v) {
240 SkScalar pt3[3] = {verts[v].fPosition.x(), verts[v].fPosition.y(), 1.f};
241 fKLM.mapHomogeneousPoints(verts[v].fKLM, pt3, 1);
242 }
243 helper.recordDraw(target, fGeometryProcessor.get(), this->pipeline());
244 }
245
246 SkMatrix fKLM;
247 SkRect fRect;
248 sk_sp<GrGeometryProcessor> fGeometryProcessor;
249
250 static constexpr int kVertsPerCubic = 4;
251 static constexpr int kIndicesPerCubic = 6;
252
253 typedef GrTestMeshDrawOp INHERITED;
254};
255
256
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000257/**
258 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
259 */
260class BezierConicEffects : public GM {
261public:
262 BezierConicEffects() {
263 this->setBGColor(0xFFFFFFFF);
264 }
265
266protected:
mtklein36352bf2015-03-25 18:17:31 -0700267 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000268 return SkString("bezier_conic_effects");
269 }
270
mtklein36352bf2015-03-25 18:17:31 -0700271 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700272 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000273 }
274
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000275
mtklein36352bf2015-03-25 18:17:31 -0700276 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400277 GrRenderTargetContext* renderTargetContext =
278 canvas->internal_private_accessTopLayerRenderTargetContext();
279 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700280 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000281 return;
282 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000283
robertphillips175dd9b2016-04-28 14:32:04 -0700284 GrContext* context = canvas->getGrContext();
285 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800286 return;
287 }
288
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000289 struct Vertex {
290 SkPoint fPosition;
291 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
292 };
293
mtkleindbfd7ab2016-09-01 11:24:54 -0700294 constexpr int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000295 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000296
297 // Mult by 3 for each edge effect type
298 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
299 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400300 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
301 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000302 int row = 0;
303 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700304 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000305
306 for (int i = 0; i < kNumConics; ++i) {
307 SkPoint baseControlPts[] = {
308 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
309 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
310 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
311 };
312 SkScalar weight = rand.nextRangeF(0.f, 2.f);
joshualittb0a8a372014-09-23 09:50:21 -0700313 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700314 sk_sp<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800315 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
bungeman06ca8ec2016-06-09 08:01:03 -0700316 gp = GrConicEffect::Make(color, SkMatrix::I(), et,
317 *context->caps(), SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800318 if (!gp) {
319 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000320 }
321
Mike Reeddf85c382017-02-14 10:59:19 -0500322 SkScalar x = col * w;
323 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000324 SkPoint controlPts[] = {
325 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
326 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
327 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
328 };
329 SkConic dst[4];
csmartdaltoncc261272017-03-23 13:38:45 -0600330 SkMatrix klm;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000331 int cnt = chop_conic(controlPts, dst, weight);
csmartdaltoncc261272017-03-23 13:38:45 -0600332 GrPathUtils::getConicKLM(controlPts, weight, &klm);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000333
334 SkPaint ctrlPtPaint;
335 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
336 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400337 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000338 }
339
340 SkPaint polyPaint;
341 polyPaint.setColor(0xffA0A0A0);
342 polyPaint.setStrokeWidth(0);
343 polyPaint.setStyle(SkPaint::kStroke_Style);
344 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
345
346 SkPaint choppedPtPaint;
347 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
348
349 for (int c = 0; c < cnt; ++c) {
350 SkPoint* pts = dst[c].fPts;
351 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400352 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000353 }
354
355 SkRect bounds;
356 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
357 //bounds.set(bPts, 2);
358 bounds.set(pts, 3);
359
360 SkPaint boundsPaint;
361 boundsPaint.setColor(0xff808080);
362 boundsPaint.setStrokeWidth(0);
363 boundsPaint.setStyle(SkPaint::kStroke_Style);
364 canvas->drawRect(bounds, boundsPaint);
365
robertphillips28a838e2016-06-23 14:07:00 -0700366 GrPaint grPaint;
Brian Salomona1633922017-01-09 11:46:10 -0500367 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000368
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400369 std::unique_ptr<GrLegacyMeshDrawOp> op =
Chris Daltonfebbffa2017-06-08 13:12:02 -0600370 BezierConicTestOp::Make(gp, bounds, color, klm);
joshualitt95964c62015-02-11 13:45:50 -0800371
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400372 renderTargetContext->priv().testingOnly_addLegacyMeshDrawOp(
Brian Salomon82f44312017-01-11 13:42:54 -0500373 std::move(grPaint), GrAAType::kNone, std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000374 }
375 ++col;
376 if (numCols == col) {
377 col = 0;
378 ++row;
379 }
380 }
381 }
382 }
383
384private:
385 // Uses the max curvature function for quads to estimate
386 // where to chop the conic. If the max curvature is not
387 // found along the curve segment it will return 1 and
388 // dst[0] is the original conic. If it returns 2 the dst[0]
389 // and dst[1] are the two new conics.
390 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
391 SkScalar t = SkFindQuadMaxCurvature(src);
392 if (t == 0) {
393 if (dst) {
394 dst[0].set(src, weight);
395 }
396 return 1;
397 } else {
398 if (dst) {
399 SkConic conic;
400 conic.set(src, weight);
caryclark414c4292016-09-26 11:03:54 -0700401 if (!conic.chopAt(t, dst)) {
402 dst[0].set(src, weight);
403 return 1;
404 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000405 }
406 return 2;
407 }
408 }
409
410 // Calls split_conic on the entire conic and then once more on each subsection.
411 // Most cases will result in either 1 conic (chop point is not within t range)
412 // or 3 points (split once and then one subsection is split again).
413 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
414 SkConic dstTemp[2];
415 int conicCnt = split_conic(src, dstTemp, weight);
416 if (2 == conicCnt) {
417 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
418 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
419 } else {
420 dst[0] = dstTemp[0];
421 }
422 return conicCnt;
423 }
424
425 typedef GM INHERITED;
426};
427
428//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800429
Brian Salomon6b316e92016-12-16 09:35:49 -0500430class BezierQuadTestOp : public GrTestMeshDrawOp {
joshualitt95964c62015-02-11 13:45:50 -0800431public:
Brian Salomon25a88092016-12-01 09:36:50 -0500432 DEFINE_OP_CLASS_ID
Brian Salomon6b316e92016-12-16 09:35:49 -0500433 const char* name() const override { return "BezierQuadTestOp"; }
joshualitt95964c62015-02-11 13:45:50 -0800434
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400435 static std::unique_ptr<GrLegacyMeshDrawOp> Make(sk_sp<GrGeometryProcessor> gp,
436 const SkRect& rect, GrColor color,
437 const GrPathUtils::QuadUVMatrix& devToUV) {
438 return std::unique_ptr<GrLegacyMeshDrawOp>(new BezierQuadTestOp(gp, rect, color, devToUV));
joshualitt95964c62015-02-11 13:45:50 -0800439 }
440
441private:
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500442 BezierQuadTestOp(sk_sp<GrGeometryProcessor> gp, const SkRect& rect, GrColor color,
Brian Salomon6b316e92016-12-16 09:35:49 -0500443 const GrPathUtils::QuadUVMatrix& devToUV)
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500444 : INHERITED(ClassID(), rect, color)
Brian Salomon6b316e92016-12-16 09:35:49 -0500445 , fDevToUV(devToUV)
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500446 , fRect(rect)
Brian Salomon6b316e92016-12-16 09:35:49 -0500447 , fGeometryProcessor(std::move(gp)) {}
joshualitt95964c62015-02-11 13:45:50 -0800448
449 struct Vertex {
450 SkPoint fPosition;
451 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
452 };
453
bsalomon342bfc22016-04-01 06:06:20 -0700454 void onPrepareDraws(Target* target) const override {
bsalomonb5238a72015-05-05 07:49:49 -0700455 QuadHelper helper;
bsalomon342bfc22016-04-01 06:06:20 -0700456 size_t vertexStride = fGeometryProcessor->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -0700457 SkASSERT(vertexStride == sizeof(Vertex));
bsalomon75398562015-08-17 12:55:38 -0700458 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
bsalomonb5238a72015-05-05 07:49:49 -0700459 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800460 return;
461 }
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500462 verts[0].fPosition.setRectFan(fRect.fLeft, fRect.fTop, fRect.fRight, fRect.fBottom,
joshualitt95964c62015-02-11 13:45:50 -0800463 sizeof(Vertex));
joshualitt95964c62015-02-11 13:45:50 -0800464 fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400465 helper.recordDraw(target, fGeometryProcessor.get(), this->pipeline());
joshualitt95964c62015-02-11 13:45:50 -0800466 }
467
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500468 GrPathUtils::QuadUVMatrix fDevToUV;
469 SkRect fRect;
bungeman06ca8ec2016-06-09 08:01:03 -0700470 sk_sp<GrGeometryProcessor> fGeometryProcessor;
joshualitt95964c62015-02-11 13:45:50 -0800471
mtkleindbfd7ab2016-09-01 11:24:54 -0700472 static constexpr int kVertsPerCubic = 4;
473 static constexpr int kIndicesPerCubic = 6;
joshualitt95964c62015-02-11 13:45:50 -0800474
Brian Salomon6b316e92016-12-16 09:35:49 -0500475 typedef GrTestMeshDrawOp INHERITED;
joshualitt95964c62015-02-11 13:45:50 -0800476};
477
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000478/**
479 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
480 */
481class BezierQuadEffects : public GM {
482public:
483 BezierQuadEffects() {
484 this->setBGColor(0xFFFFFFFF);
485 }
486
487protected:
mtklein36352bf2015-03-25 18:17:31 -0700488 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000489 return SkString("bezier_quad_effects");
490 }
491
mtklein36352bf2015-03-25 18:17:31 -0700492 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700493 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000494 }
495
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000496
mtklein36352bf2015-03-25 18:17:31 -0700497 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400498 GrRenderTargetContext* renderTargetContext =
499 canvas->internal_private_accessTopLayerRenderTargetContext();
500 if (!renderTargetContext) {
halcanary2a243382015-09-09 08:16:41 -0700501 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000502 return;
503 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000504
robertphillips175dd9b2016-04-28 14:32:04 -0700505 GrContext* context = canvas->getGrContext();
506 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800507 return;
508 }
509
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000510 struct Vertex {
511 SkPoint fPosition;
512 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
513 };
514
mtkleindbfd7ab2016-09-01 11:24:54 -0700515 constexpr int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000516 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000517
518 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
519 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
Brian Osman11052242016-10-27 14:47:55 -0400520 SkScalar w = SkIntToScalar(renderTargetContext->width()) / numCols;
521 SkScalar h = SkIntToScalar(renderTargetContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000522 int row = 0;
523 int col = 0;
mtkleindbfd7ab2016-09-01 11:24:54 -0700524 constexpr GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000525
526 for (int i = 0; i < kNumQuads; ++i) {
527 SkPoint baseControlPts[] = {
528 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
529 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
530 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
531 };
joshualittb0a8a372014-09-23 09:50:21 -0700532 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700533 sk_sp<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800534 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
bungeman06ca8ec2016-06-09 08:01:03 -0700535 gp = GrQuadEffect::Make(color, SkMatrix::I(), et,
536 *context->caps(), SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800537 if (!gp) {
538 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000539 }
540
Mike Reeddf85c382017-02-14 10:59:19 -0500541 SkScalar x = col * w;
542 SkScalar y = row * h;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000543 SkPoint controlPts[] = {
544 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
545 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
546 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
547 };
548 SkPoint chopped[5];
549 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
550
551 SkPaint ctrlPtPaint;
552 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
553 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400554 canvas->drawCircle(controlPts[i], 6.f, ctrlPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000555 }
556
557 SkPaint polyPaint;
558 polyPaint.setColor(0xffA0A0A0);
559 polyPaint.setStrokeWidth(0);
560 polyPaint.setStyle(SkPaint::kStroke_Style);
561 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
562
563 SkPaint choppedPtPaint;
564 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
565
566 for (int c = 0; c < cnt; ++c) {
567 SkPoint* pts = chopped + 2 * c;
568
569 for (int i = 0; i < 3; ++i) {
Hal Canary23e474c2017-05-15 13:35:35 -0400570 canvas->drawCircle(pts[i], 3.f, choppedPtPaint);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000571 }
572
573 SkRect bounds;
574 bounds.set(pts, 3);
575
576 SkPaint boundsPaint;
577 boundsPaint.setColor(0xff808080);
578 boundsPaint.setStrokeWidth(0);
579 boundsPaint.setStyle(SkPaint::kStroke_Style);
580 canvas->drawRect(bounds, boundsPaint);
581
robertphillips28a838e2016-06-23 14:07:00 -0700582 GrPaint grPaint;
Brian Salomona1633922017-01-09 11:46:10 -0500583 grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
joshualitt3f284d72015-02-11 11:34:58 -0800584
joshualitt95964c62015-02-11 13:45:50 -0800585 GrPathUtils::QuadUVMatrix DevToUV(pts);
586
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400587 std::unique_ptr<GrLegacyMeshDrawOp> op =
Brian Salomonf8334782017-01-03 09:42:58 -0500588 BezierQuadTestOp::Make(gp, bounds, color, DevToUV);
joshualitt95964c62015-02-11 13:45:50 -0800589
Brian Salomond3ccb0a2017-04-03 10:38:00 -0400590 renderTargetContext->priv().testingOnly_addLegacyMeshDrawOp(
Brian Salomon82f44312017-01-11 13:42:54 -0500591 std::move(grPaint), GrAAType::kNone, std::move(op));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000592 }
593 ++col;
594 if (numCols == col) {
595 col = 0;
596 ++row;
597 }
598 }
599 }
600 }
601
602private:
603 typedef GM INHERITED;
604};
605
halcanary385fe4d2015-08-26 13:07:48 -0700606DEF_GM(return new BezierCubicEffects;)
607DEF_GM(return new BezierConicEffects;)
608DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000609}
610
611#endif