blob: ae1c37fdf6031ecd5a987c97c6b0bf2bd2be2e85 [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
robertphillips391395d2016-03-02 09:26:36 -080014#include "GrDrawContextPriv.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
joshualitt2771b562015-08-07 12:46:26 -070021#include "batches/GrTestBatch.h"
22
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 +000025static inline SkScalar eval_line(const SkPoint& p, const SkScalar lineEq[3], SkScalar sign) {
26 return sign * (lineEq[0] * p.fX + lineEq[1] * p.fY + lineEq[2]);
27}
28
29namespace skiagm {
joshualitt95964c62015-02-11 13:45:50 -080030
31class BezierCubicOrConicTestBatch : public GrTestBatch {
32public:
reed1b55a962015-09-17 20:16:13 -070033 DEFINE_BATCH_CLASS_ID
joshualitt95964c62015-02-11 13:45:50 -080034
mtklein36352bf2015-03-25 18:17:31 -070035 const char* name() const override { return "BezierCubicOrConicTestBatch"; }
joshualitt95964c62015-02-11 13:45:50 -080036
bungeman06ca8ec2016-06-09 08:01:03 -070037 BezierCubicOrConicTestBatch(sk_sp<GrGeometryProcessor> gp, const SkRect& bounds,
bsalomon342bfc22016-04-01 06:06:20 -070038 GrColor color, const SkScalar klmEqs[9], SkScalar sign)
39 : INHERITED(ClassID(), bounds, color)
bungeman06ca8ec2016-06-09 08:01:03 -070040 , fGeometryProcessor(std::move(gp)) {
joshualitt95964c62015-02-11 13:45:50 -080041 for (int i = 0; i < 9; i++) {
42 fKlmEqs[i] = klmEqs[i];
43 }
joshualitt95964c62015-02-11 13:45:50 -080044 fSign = sign;
45 }
46
bsalomon342bfc22016-04-01 06:06:20 -070047private:
48
joshualitt95964c62015-02-11 13:45:50 -080049 struct Vertex {
50 SkPoint fPosition;
51 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
52 };
53
bsalomon342bfc22016-04-01 06:06:20 -070054 void onPrepareDraws(Target* target) const override {
bsalomonb5238a72015-05-05 07:49:49 -070055 QuadHelper helper;
bsalomon342bfc22016-04-01 06:06:20 -070056 size_t vertexStride = fGeometryProcessor->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -070057 SkASSERT(vertexStride == sizeof(Vertex));
bsalomon75398562015-08-17 12:55:38 -070058 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
bsalomonb5238a72015-05-05 07:49:49 -070059 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -080060 return;
61 }
bsalomon342bfc22016-04-01 06:06:20 -070062 const SkRect& bounds = this->bounds();
63 verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom,
joshualitt95964c62015-02-11 13:45:50 -080064 sizeof(Vertex));
65 for (int v = 0; v < 4; ++v) {
66 verts[v].fKLM[0] = eval_line(verts[v].fPosition, fKlmEqs + 0, fSign);
67 verts[v].fKLM[1] = eval_line(verts[v].fPosition, fKlmEqs + 3, fSign);
68 verts[v].fKLM[2] = eval_line(verts[v].fPosition, fKlmEqs + 6, 1.f);
69 }
bungeman06ca8ec2016-06-09 08:01:03 -070070 helper.recordDraw(target, fGeometryProcessor.get());
joshualitt95964c62015-02-11 13:45:50 -080071 }
72
bungeman06ca8ec2016-06-09 08:01:03 -070073 SkScalar fKlmEqs[9];
74 SkScalar fSign;
75 sk_sp<GrGeometryProcessor> fGeometryProcessor;
joshualitt95964c62015-02-11 13:45:50 -080076
77 static const int kVertsPerCubic = 4;
78 static const int kIndicesPerCubic = 6;
79
80 typedef GrTestBatch INHERITED;
81};
82
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000083/**
84 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
85 */
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000086class BezierCubicEffects : public GM {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000087public:
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000088 BezierCubicEffects() {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000089 this->setBGColor(0xFFFFFFFF);
90 }
91
92protected:
mtklein36352bf2015-03-25 18:17:31 -070093 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000094 return SkString("bezier_cubic_effects");
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000095 }
96
mtklein36352bf2015-03-25 18:17:31 -070097 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -070098 return SkISize::Make(800, 800);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000099 }
100
mtklein36352bf2015-03-25 18:17:31 -0700101 void onDraw(SkCanvas* canvas) override {
robertphillips175dd9b2016-04-28 14:32:04 -0700102 GrDrawContext* drawContext = canvas->internal_private_accessTopLayerDrawContext();
103 if (!drawContext) {
halcanary2a243382015-09-09 08:16:41 -0700104 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000105 return;
106 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000107
robertphillips175dd9b2016-04-28 14:32:04 -0700108 GrContext* context = canvas->getGrContext();
109 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800110 return;
111 }
112
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000113 struct Vertex {
114 SkPoint fPosition;
115 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
116 };
117
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000118 static const int kNumCubics = 15;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000119 SkRandom rand;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000120
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000121 // Mult by 3 for each edge effect type
122 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
123 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
robertphillips175dd9b2016-04-28 14:32:04 -0700124 SkScalar w = SkIntToScalar(drawContext->width()) / numCols;
125 SkScalar h = SkIntToScalar(drawContext->height()) / numRows;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000126 int row = 0;
127 int col = 0;
joshualitt88c23fc2015-05-13 14:18:07 -0700128 static const GrColor color = 0xff000000;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000129
130 for (int i = 0; i < kNumCubics; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000131 SkPoint baseControlPts[] = {
132 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
133 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
134 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
135 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000136 };
joshualittb0a8a372014-09-23 09:50:21 -0700137 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700138 sk_sp<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800139 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
bungeman06ca8ec2016-06-09 08:01:03 -0700140 gp = GrCubicEffect::Make(color, SkMatrix::I(), et, *context->caps());
joshualittf5883a62016-01-13 07:47:38 -0800141 if (!gp) {
142 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000143 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000144 SkScalar x = SkScalarMul(col, w);
145 SkScalar y = SkScalarMul(row, h);
146 SkPoint controlPts[] = {
147 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
148 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
149 {x + baseControlPts[2].fX, y + baseControlPts[2].fY},
150 {x + baseControlPts[3].fX, y + baseControlPts[3].fY}
151 };
152 SkPoint chopped[10];
153 SkScalar klmEqs[9];
154 SkScalar klmSigns[3];
155 int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
156 chopped,
157 klmEqs,
158 klmSigns);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000159
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000160 SkPaint ctrlPtPaint;
161 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000162 for (int i = 0; i < 4; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000163 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000164 }
165
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000166 SkPaint polyPaint;
167 polyPaint.setColor(0xffA0A0A0);
168 polyPaint.setStrokeWidth(0);
169 polyPaint.setStyle(SkPaint::kStroke_Style);
170 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000171
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000172 SkPaint choppedPtPaint;
173 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000174
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000175 for (int c = 0; c < cnt; ++c) {
176 SkPoint* pts = chopped + 3 * c;
177
178 for (int i = 0; i < 4; ++i) {
179 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
180 }
181
182 SkRect bounds;
183 bounds.set(pts, 4);
184
185 SkPaint boundsPaint;
186 boundsPaint.setColor(0xff808080);
187 boundsPaint.setStrokeWidth(0);
188 boundsPaint.setStyle(SkPaint::kStroke_Style);
189 canvas->drawRect(bounds, boundsPaint);
190
egdaniel8dd688b2015-01-22 10:16:09 -0800191 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800192 pipelineBuilder.setXPFactory(
bungeman06ca8ec2016-06-09 08:01:03 -0700193 GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000194
bsalomonabd30f52015-08-13 13:34:48 -0700195 SkAutoTUnref<GrDrawBatch> batch(
bsalomon342bfc22016-04-01 06:06:20 -0700196 new BezierCubicOrConicTestBatch(gp, bounds, color, klmEqs, klmSigns[c]));
joshualitt95964c62015-02-11 13:45:50 -0800197
robertphillips391395d2016-03-02 09:26:36 -0800198 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000199 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000200 ++col;
201 if (numCols == col) {
202 col = 0;
203 ++row;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000204 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000205 }
206 }
207 }
208
209private:
210 typedef GM INHERITED;
211};
212
213//////////////////////////////////////////////////////////////////////////////
214
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000215/**
216 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
217 */
218class BezierConicEffects : public GM {
219public:
220 BezierConicEffects() {
221 this->setBGColor(0xFFFFFFFF);
222 }
223
224protected:
mtklein36352bf2015-03-25 18:17:31 -0700225 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000226 return SkString("bezier_conic_effects");
227 }
228
mtklein36352bf2015-03-25 18:17:31 -0700229 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700230 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000231 }
232
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000233
mtklein36352bf2015-03-25 18:17:31 -0700234 void onDraw(SkCanvas* canvas) override {
robertphillips175dd9b2016-04-28 14:32:04 -0700235 GrDrawContext* drawContext = canvas->internal_private_accessTopLayerDrawContext();
236 if (!drawContext) {
halcanary2a243382015-09-09 08:16:41 -0700237 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000238 return;
239 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000240
robertphillips175dd9b2016-04-28 14:32:04 -0700241 GrContext* context = canvas->getGrContext();
242 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800243 return;
244 }
245
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000246 struct Vertex {
247 SkPoint fPosition;
248 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
249 };
250
251 static const int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000252 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000253
254 // Mult by 3 for each edge effect type
255 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
256 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
robertphillips175dd9b2016-04-28 14:32:04 -0700257 SkScalar w = SkIntToScalar(drawContext->width()) / numCols;
258 SkScalar h = SkIntToScalar(drawContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000259 int row = 0;
260 int col = 0;
joshualitt88c23fc2015-05-13 14:18:07 -0700261 static const GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000262
263 for (int i = 0; i < kNumConics; ++i) {
264 SkPoint baseControlPts[] = {
265 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
266 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
267 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
268 };
269 SkScalar weight = rand.nextRangeF(0.f, 2.f);
joshualittb0a8a372014-09-23 09:50:21 -0700270 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700271 sk_sp<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800272 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
bungeman06ca8ec2016-06-09 08:01:03 -0700273 gp = GrConicEffect::Make(color, SkMatrix::I(), et,
274 *context->caps(), SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800275 if (!gp) {
276 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000277 }
278
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000279 SkScalar x = SkScalarMul(col, w);
280 SkScalar y = SkScalarMul(row, h);
281 SkPoint controlPts[] = {
282 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
283 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
284 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
285 };
286 SkConic dst[4];
287 SkScalar klmEqs[9];
288 int cnt = chop_conic(controlPts, dst, weight);
289 GrPathUtils::getConicKLM(controlPts, weight, klmEqs);
290
291 SkPaint ctrlPtPaint;
292 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
293 for (int i = 0; i < 3; ++i) {
294 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
295 }
296
297 SkPaint polyPaint;
298 polyPaint.setColor(0xffA0A0A0);
299 polyPaint.setStrokeWidth(0);
300 polyPaint.setStyle(SkPaint::kStroke_Style);
301 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
302
303 SkPaint choppedPtPaint;
304 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
305
306 for (int c = 0; c < cnt; ++c) {
307 SkPoint* pts = dst[c].fPts;
308 for (int i = 0; i < 3; ++i) {
309 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
310 }
311
312 SkRect bounds;
313 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
314 //bounds.set(bPts, 2);
315 bounds.set(pts, 3);
316
317 SkPaint boundsPaint;
318 boundsPaint.setColor(0xff808080);
319 boundsPaint.setStrokeWidth(0);
320 boundsPaint.setStyle(SkPaint::kStroke_Style);
321 canvas->drawRect(bounds, boundsPaint);
322
egdaniel8dd688b2015-01-22 10:16:09 -0800323 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800324 pipelineBuilder.setXPFactory(
bungeman06ca8ec2016-06-09 08:01:03 -0700325 GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000326
bsalomonabd30f52015-08-13 13:34:48 -0700327 SkAutoTUnref<GrDrawBatch> batch(
bsalomon342bfc22016-04-01 06:06:20 -0700328 new BezierCubicOrConicTestBatch(gp, bounds, color, klmEqs, 1.f));
joshualitt95964c62015-02-11 13:45:50 -0800329
robertphillips391395d2016-03-02 09:26:36 -0800330 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000331 }
332 ++col;
333 if (numCols == col) {
334 col = 0;
335 ++row;
336 }
337 }
338 }
339 }
340
341private:
342 // Uses the max curvature function for quads to estimate
343 // where to chop the conic. If the max curvature is not
344 // found along the curve segment it will return 1 and
345 // dst[0] is the original conic. If it returns 2 the dst[0]
346 // and dst[1] are the two new conics.
347 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
348 SkScalar t = SkFindQuadMaxCurvature(src);
349 if (t == 0) {
350 if (dst) {
351 dst[0].set(src, weight);
352 }
353 return 1;
354 } else {
355 if (dst) {
356 SkConic conic;
357 conic.set(src, weight);
358 conic.chopAt(t, dst);
359 }
360 return 2;
361 }
362 }
363
364 // Calls split_conic on the entire conic and then once more on each subsection.
365 // Most cases will result in either 1 conic (chop point is not within t range)
366 // or 3 points (split once and then one subsection is split again).
367 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
368 SkConic dstTemp[2];
369 int conicCnt = split_conic(src, dstTemp, weight);
370 if (2 == conicCnt) {
371 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
372 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
373 } else {
374 dst[0] = dstTemp[0];
375 }
376 return conicCnt;
377 }
378
379 typedef GM INHERITED;
380};
381
382//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800383
384class BezierQuadTestBatch : public GrTestBatch {
385public:
reed1b55a962015-09-17 20:16:13 -0700386 DEFINE_BATCH_CLASS_ID
mtklein36352bf2015-03-25 18:17:31 -0700387 const char* name() const override { return "BezierQuadTestBatch"; }
joshualitt95964c62015-02-11 13:45:50 -0800388
bungeman06ca8ec2016-06-09 08:01:03 -0700389 BezierQuadTestBatch(sk_sp<GrGeometryProcessor> gp, const SkRect& bounds, GrColor color,
bsalomon342bfc22016-04-01 06:06:20 -0700390 const GrPathUtils::QuadUVMatrix& devToUV)
391 : INHERITED(ClassID(), bounds, color)
392 , fDevToUV(devToUV)
bungeman06ca8ec2016-06-09 08:01:03 -0700393 , fGeometryProcessor(std::move(gp)) {
joshualitt95964c62015-02-11 13:45:50 -0800394 }
395
396private:
joshualitt95964c62015-02-11 13:45:50 -0800397
398 struct Vertex {
399 SkPoint fPosition;
400 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
401 };
402
bsalomon342bfc22016-04-01 06:06:20 -0700403 void onPrepareDraws(Target* target) const override {
bsalomonb5238a72015-05-05 07:49:49 -0700404 QuadHelper helper;
bsalomon342bfc22016-04-01 06:06:20 -0700405 size_t vertexStride = fGeometryProcessor->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -0700406 SkASSERT(vertexStride == sizeof(Vertex));
bsalomon75398562015-08-17 12:55:38 -0700407 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
bsalomonb5238a72015-05-05 07:49:49 -0700408 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800409 return;
410 }
bsalomon342bfc22016-04-01 06:06:20 -0700411 const SkRect& bounds = this->bounds();
412 verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom,
joshualitt95964c62015-02-11 13:45:50 -0800413 sizeof(Vertex));
joshualitt95964c62015-02-11 13:45:50 -0800414 fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
bungeman06ca8ec2016-06-09 08:01:03 -0700415 helper.recordDraw(target, fGeometryProcessor.get());
joshualitt95964c62015-02-11 13:45:50 -0800416 }
417
bungeman06ca8ec2016-06-09 08:01:03 -0700418 GrPathUtils::QuadUVMatrix fDevToUV;
419 sk_sp<GrGeometryProcessor> fGeometryProcessor;
joshualitt95964c62015-02-11 13:45:50 -0800420
421 static const int kVertsPerCubic = 4;
422 static const int kIndicesPerCubic = 6;
423
424 typedef GrTestBatch INHERITED;
425};
426
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000427/**
428 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
429 */
430class BezierQuadEffects : public GM {
431public:
432 BezierQuadEffects() {
433 this->setBGColor(0xFFFFFFFF);
434 }
435
436protected:
mtklein36352bf2015-03-25 18:17:31 -0700437 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000438 return SkString("bezier_quad_effects");
439 }
440
mtklein36352bf2015-03-25 18:17:31 -0700441 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700442 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000443 }
444
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000445
mtklein36352bf2015-03-25 18:17:31 -0700446 void onDraw(SkCanvas* canvas) override {
robertphillips175dd9b2016-04-28 14:32:04 -0700447 GrDrawContext* drawContext = canvas->internal_private_accessTopLayerDrawContext();
448 if (!drawContext) {
halcanary2a243382015-09-09 08:16:41 -0700449 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000450 return;
451 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000452
robertphillips175dd9b2016-04-28 14:32:04 -0700453 GrContext* context = canvas->getGrContext();
454 if (!context) {
joshualittf5883a62016-01-13 07:47:38 -0800455 return;
456 }
457
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000458 struct Vertex {
459 SkPoint fPosition;
460 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
461 };
462
463 static const int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000464 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000465
466 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
467 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
robertphillips175dd9b2016-04-28 14:32:04 -0700468 SkScalar w = SkIntToScalar(drawContext->width()) / numCols;
469 SkScalar h = SkIntToScalar(drawContext->height()) / numRows;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000470 int row = 0;
471 int col = 0;
joshualitt88c23fc2015-05-13 14:18:07 -0700472 static const GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000473
474 for (int i = 0; i < kNumQuads; ++i) {
475 SkPoint baseControlPts[] = {
476 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
477 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
478 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
479 };
joshualittb0a8a372014-09-23 09:50:21 -0700480 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
bungeman06ca8ec2016-06-09 08:01:03 -0700481 sk_sp<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800482 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
bungeman06ca8ec2016-06-09 08:01:03 -0700483 gp = GrQuadEffect::Make(color, SkMatrix::I(), et,
484 *context->caps(), SkMatrix::I(), false);
joshualittf5883a62016-01-13 07:47:38 -0800485 if (!gp) {
486 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000487 }
488
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000489 SkScalar x = SkScalarMul(col, w);
490 SkScalar y = SkScalarMul(row, h);
491 SkPoint controlPts[] = {
492 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
493 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
494 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
495 };
496 SkPoint chopped[5];
497 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
498
499 SkPaint ctrlPtPaint;
500 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
501 for (int i = 0; i < 3; ++i) {
502 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
503 }
504
505 SkPaint polyPaint;
506 polyPaint.setColor(0xffA0A0A0);
507 polyPaint.setStrokeWidth(0);
508 polyPaint.setStyle(SkPaint::kStroke_Style);
509 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
510
511 SkPaint choppedPtPaint;
512 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
513
514 for (int c = 0; c < cnt; ++c) {
515 SkPoint* pts = chopped + 2 * c;
516
517 for (int i = 0; i < 3; ++i) {
518 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
519 }
520
521 SkRect bounds;
522 bounds.set(pts, 3);
523
524 SkPaint boundsPaint;
525 boundsPaint.setColor(0xff808080);
526 boundsPaint.setStrokeWidth(0);
527 boundsPaint.setStyle(SkPaint::kStroke_Style);
528 canvas->drawRect(bounds, boundsPaint);
529
egdaniel8dd688b2015-01-22 10:16:09 -0800530 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800531 pipelineBuilder.setXPFactory(
bungeman06ca8ec2016-06-09 08:01:03 -0700532 GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode));
joshualitt3f284d72015-02-11 11:34:58 -0800533
joshualitt95964c62015-02-11 13:45:50 -0800534 GrPathUtils::QuadUVMatrix DevToUV(pts);
535
bsalomon342bfc22016-04-01 06:06:20 -0700536 SkAutoTUnref<GrDrawBatch> batch(
537 new BezierQuadTestBatch(gp, bounds, color, DevToUV));
joshualitt95964c62015-02-11 13:45:50 -0800538
robertphillips391395d2016-03-02 09:26:36 -0800539 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000540 }
541 ++col;
542 if (numCols == col) {
543 col = 0;
544 ++row;
545 }
546 }
547 }
548 }
549
550private:
551 typedef GM INHERITED;
552};
553
halcanary385fe4d2015-08-26 13:07:48 -0700554DEF_GM(return new BezierCubicEffects;)
555DEF_GM(return new BezierConicEffects;)
556DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000557}
558
559#endif