blob: 84e2a69e1954a19a2b13b88f876d113469ffee9d [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"
19#include "SkDevice.h"
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000020#include "SkGeometry.h"
21
joshualitt2771b562015-08-07 12:46:26 -070022#include "batches/GrTestBatch.h"
23
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000024#include "effects/GrBezierEffect.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000025
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000026static inline SkScalar eval_line(const SkPoint& p, const SkScalar lineEq[3], SkScalar sign) {
27 return sign * (lineEq[0] * p.fX + lineEq[1] * p.fY + lineEq[2]);
28}
29
30namespace skiagm {
joshualitt95964c62015-02-11 13:45:50 -080031
32class BezierCubicOrConicTestBatch : public GrTestBatch {
33public:
reed1b55a962015-09-17 20:16:13 -070034 DEFINE_BATCH_CLASS_ID
joshualitt95964c62015-02-11 13:45:50 -080035
mtklein36352bf2015-03-25 18:17:31 -070036 const char* name() const override { return "BezierCubicOrConicTestBatch"; }
joshualitt95964c62015-02-11 13:45:50 -080037
bsalomon342bfc22016-04-01 06:06:20 -070038 BezierCubicOrConicTestBatch(const GrGeometryProcessor* gp, const SkRect& bounds,
39 GrColor color, const SkScalar klmEqs[9], SkScalar sign)
40 : INHERITED(ClassID(), bounds, color)
41 , fGeometryProcessor(SkRef(gp)) {
joshualitt95964c62015-02-11 13:45:50 -080042 for (int i = 0; i < 9; i++) {
43 fKlmEqs[i] = klmEqs[i];
44 }
joshualitt95964c62015-02-11 13:45:50 -080045 fSign = sign;
46 }
47
bsalomon342bfc22016-04-01 06:06:20 -070048private:
49
joshualitt95964c62015-02-11 13:45:50 -080050 struct Vertex {
51 SkPoint fPosition;
52 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
53 };
54
bsalomon342bfc22016-04-01 06:06:20 -070055 void onPrepareDraws(Target* target) const override {
bsalomonb5238a72015-05-05 07:49:49 -070056 QuadHelper helper;
bsalomon342bfc22016-04-01 06:06:20 -070057 size_t vertexStride = fGeometryProcessor->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -070058 SkASSERT(vertexStride == sizeof(Vertex));
bsalomon75398562015-08-17 12:55:38 -070059 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
bsalomonb5238a72015-05-05 07:49:49 -070060 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -080061 return;
62 }
bsalomon342bfc22016-04-01 06:06:20 -070063 const SkRect& bounds = this->bounds();
64 verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom,
joshualitt95964c62015-02-11 13:45:50 -080065 sizeof(Vertex));
66 for (int v = 0; v < 4; ++v) {
67 verts[v].fKLM[0] = eval_line(verts[v].fPosition, fKlmEqs + 0, fSign);
68 verts[v].fKLM[1] = eval_line(verts[v].fPosition, fKlmEqs + 3, fSign);
69 verts[v].fKLM[2] = eval_line(verts[v].fPosition, fKlmEqs + 6, 1.f);
70 }
bsalomon342bfc22016-04-01 06:06:20 -070071 helper.recordDraw(target, fGeometryProcessor);
joshualitt95964c62015-02-11 13:45:50 -080072 }
73
bsalomon342bfc22016-04-01 06:06:20 -070074 SkScalar fKlmEqs[9];
75 SkScalar fSign;
76 SkAutoTUnref<const GrGeometryProcessor> fGeometryProcessor;
joshualitt95964c62015-02-11 13:45:50 -080077
78 static const int kVertsPerCubic = 4;
79 static const int kIndicesPerCubic = 6;
80
81 typedef GrTestBatch INHERITED;
82};
83
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000084/**
85 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
86 */
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000087class BezierCubicEffects : public GM {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000088public:
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000089 BezierCubicEffects() {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000090 this->setBGColor(0xFFFFFFFF);
91 }
92
93protected:
mtklein36352bf2015-03-25 18:17:31 -070094 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000095 return SkString("bezier_cubic_effects");
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000096 }
97
mtklein36352bf2015-03-25 18:17:31 -070098 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -070099 return SkISize::Make(800, 800);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000100 }
101
mtklein36352bf2015-03-25 18:17:31 -0700102 void onDraw(SkCanvas* canvas) override {
reed@google.com9c135db2014-03-12 18:28:35 +0000103 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -0700104 if (nullptr == rt) {
halcanary2a243382015-09-09 08:16:41 -0700105 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000106 return;
107 }
108 GrContext* context = rt->getContext();
halcanary96fcdcc2015-08-27 07:41:13 -0700109 if (nullptr == context) {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000110 return;
111 }
112
joshualittf5883a62016-01-13 07:47:38 -0800113 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
114 if (!drawContext) {
115 return;
116 }
117
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000118 struct Vertex {
119 SkPoint fPosition;
120 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
121 };
122
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000123 static const int kNumCubics = 15;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000124 SkRandom rand;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000125
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000126 // Mult by 3 for each edge effect type
127 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
128 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000129 SkScalar w = SkIntToScalar(rt->width()) / numCols;
130 SkScalar h = SkIntToScalar(rt->height()) / numRows;
131 int row = 0;
132 int col = 0;
joshualitt88c23fc2015-05-13 14:18:07 -0700133 static const GrColor color = 0xff000000;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000134
135 for (int i = 0; i < kNumCubics; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000136 SkPoint baseControlPts[] = {
137 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
138 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
139 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
140 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000141 };
joshualittb0a8a372014-09-23 09:50:21 -0700142 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
143 SkAutoTUnref<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800144 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
145 gp.reset(GrCubicEffect::Create(color, SkMatrix::I(), et,
146 *context->caps()));
147 if (!gp) {
148 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000149 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000150 SkScalar x = SkScalarMul(col, w);
151 SkScalar y = SkScalarMul(row, h);
152 SkPoint controlPts[] = {
153 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
154 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
155 {x + baseControlPts[2].fX, y + baseControlPts[2].fY},
156 {x + baseControlPts[3].fX, y + baseControlPts[3].fY}
157 };
158 SkPoint chopped[10];
159 SkScalar klmEqs[9];
160 SkScalar klmSigns[3];
161 int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
162 chopped,
163 klmEqs,
164 klmSigns);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000165
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000166 SkPaint ctrlPtPaint;
167 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000168 for (int i = 0; i < 4; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000169 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000170 }
171
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000172 SkPaint polyPaint;
173 polyPaint.setColor(0xffA0A0A0);
174 polyPaint.setStrokeWidth(0);
175 polyPaint.setStyle(SkPaint::kStroke_Style);
176 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000177
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000178 SkPaint choppedPtPaint;
179 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000180
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000181 for (int c = 0; c < cnt; ++c) {
182 SkPoint* pts = chopped + 3 * c;
183
184 for (int i = 0; i < 4; ++i) {
185 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
186 }
187
188 SkRect bounds;
189 bounds.set(pts, 4);
190
191 SkPaint boundsPaint;
192 boundsPaint.setColor(0xff808080);
193 boundsPaint.setStrokeWidth(0);
194 boundsPaint.setStyle(SkPaint::kStroke_Style);
195 canvas->drawRect(bounds, boundsPaint);
196
egdaniel8dd688b2015-01-22 10:16:09 -0800197 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800198 pipelineBuilder.setXPFactory(
199 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
egdaniel8dd688b2015-01-22 10:16:09 -0800200 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000201
bsalomonabd30f52015-08-13 13:34:48 -0700202 SkAutoTUnref<GrDrawBatch> batch(
bsalomon342bfc22016-04-01 06:06:20 -0700203 new BezierCubicOrConicTestBatch(gp, bounds, color, klmEqs, klmSigns[c]));
joshualitt95964c62015-02-11 13:45:50 -0800204
robertphillips391395d2016-03-02 09:26:36 -0800205 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000206 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000207 ++col;
208 if (numCols == col) {
209 col = 0;
210 ++row;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000211 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000212 }
213 }
214 }
215
216private:
217 typedef GM INHERITED;
218};
219
220//////////////////////////////////////////////////////////////////////////////
221
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000222/**
223 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
224 */
225class BezierConicEffects : public GM {
226public:
227 BezierConicEffects() {
228 this->setBGColor(0xFFFFFFFF);
229 }
230
231protected:
mtklein36352bf2015-03-25 18:17:31 -0700232 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000233 return SkString("bezier_conic_effects");
234 }
235
mtklein36352bf2015-03-25 18:17:31 -0700236 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700237 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000238 }
239
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000240
mtklein36352bf2015-03-25 18:17:31 -0700241 void onDraw(SkCanvas* canvas) override {
reed@google.com9c135db2014-03-12 18:28:35 +0000242 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -0700243 if (nullptr == rt) {
halcanary2a243382015-09-09 08:16:41 -0700244 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000245 return;
246 }
247 GrContext* context = rt->getContext();
halcanary96fcdcc2015-08-27 07:41:13 -0700248 if (nullptr == context) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000249 return;
250 }
251
joshualittf5883a62016-01-13 07:47:38 -0800252 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
253 if (!drawContext) {
254 return;
255 }
256
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000257 struct Vertex {
258 SkPoint fPosition;
259 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
260 };
261
262 static const int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000263 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000264
265 // Mult by 3 for each edge effect type
266 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
267 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
268 SkScalar w = SkIntToScalar(rt->width()) / numCols;
269 SkScalar h = SkIntToScalar(rt->height()) / numRows;
270 int row = 0;
271 int col = 0;
joshualitt88c23fc2015-05-13 14:18:07 -0700272 static const GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000273
274 for (int i = 0; i < kNumConics; ++i) {
275 SkPoint baseControlPts[] = {
276 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
277 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
278 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
279 };
280 SkScalar weight = rand.nextRangeF(0.f, 2.f);
joshualittb0a8a372014-09-23 09:50:21 -0700281 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
282 SkAutoTUnref<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800283 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
284 gp.reset(GrConicEffect::Create(color, SkMatrix::I(), et,
285 *context->caps(), SkMatrix::I(), false));
286 if (!gp) {
287 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000288 }
289
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000290 SkScalar x = SkScalarMul(col, w);
291 SkScalar y = SkScalarMul(row, h);
292 SkPoint controlPts[] = {
293 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
294 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
295 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
296 };
297 SkConic dst[4];
298 SkScalar klmEqs[9];
299 int cnt = chop_conic(controlPts, dst, weight);
300 GrPathUtils::getConicKLM(controlPts, weight, klmEqs);
301
302 SkPaint ctrlPtPaint;
303 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
304 for (int i = 0; i < 3; ++i) {
305 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
306 }
307
308 SkPaint polyPaint;
309 polyPaint.setColor(0xffA0A0A0);
310 polyPaint.setStrokeWidth(0);
311 polyPaint.setStyle(SkPaint::kStroke_Style);
312 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
313
314 SkPaint choppedPtPaint;
315 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
316
317 for (int c = 0; c < cnt; ++c) {
318 SkPoint* pts = dst[c].fPts;
319 for (int i = 0; i < 3; ++i) {
320 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
321 }
322
323 SkRect bounds;
324 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
325 //bounds.set(bPts, 2);
326 bounds.set(pts, 3);
327
328 SkPaint boundsPaint;
329 boundsPaint.setColor(0xff808080);
330 boundsPaint.setStrokeWidth(0);
331 boundsPaint.setStyle(SkPaint::kStroke_Style);
332 canvas->drawRect(bounds, boundsPaint);
333
egdaniel8dd688b2015-01-22 10:16:09 -0800334 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800335 pipelineBuilder.setXPFactory(
336 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
egdaniel8dd688b2015-01-22 10:16:09 -0800337 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000338
bsalomonabd30f52015-08-13 13:34:48 -0700339 SkAutoTUnref<GrDrawBatch> batch(
bsalomon342bfc22016-04-01 06:06:20 -0700340 new BezierCubicOrConicTestBatch(gp, bounds, color, klmEqs, 1.f));
joshualitt95964c62015-02-11 13:45:50 -0800341
robertphillips391395d2016-03-02 09:26:36 -0800342 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000343 }
344 ++col;
345 if (numCols == col) {
346 col = 0;
347 ++row;
348 }
349 }
350 }
351 }
352
353private:
354 // Uses the max curvature function for quads to estimate
355 // where to chop the conic. If the max curvature is not
356 // found along the curve segment it will return 1 and
357 // dst[0] is the original conic. If it returns 2 the dst[0]
358 // and dst[1] are the two new conics.
359 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
360 SkScalar t = SkFindQuadMaxCurvature(src);
361 if (t == 0) {
362 if (dst) {
363 dst[0].set(src, weight);
364 }
365 return 1;
366 } else {
367 if (dst) {
368 SkConic conic;
369 conic.set(src, weight);
370 conic.chopAt(t, dst);
371 }
372 return 2;
373 }
374 }
375
376 // Calls split_conic on the entire conic and then once more on each subsection.
377 // Most cases will result in either 1 conic (chop point is not within t range)
378 // or 3 points (split once and then one subsection is split again).
379 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
380 SkConic dstTemp[2];
381 int conicCnt = split_conic(src, dstTemp, weight);
382 if (2 == conicCnt) {
383 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
384 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
385 } else {
386 dst[0] = dstTemp[0];
387 }
388 return conicCnt;
389 }
390
391 typedef GM INHERITED;
392};
393
394//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800395
396class BezierQuadTestBatch : public GrTestBatch {
397public:
reed1b55a962015-09-17 20:16:13 -0700398 DEFINE_BATCH_CLASS_ID
mtklein36352bf2015-03-25 18:17:31 -0700399 const char* name() const override { return "BezierQuadTestBatch"; }
joshualitt95964c62015-02-11 13:45:50 -0800400
bsalomon342bfc22016-04-01 06:06:20 -0700401 BezierQuadTestBatch(const GrGeometryProcessor* gp, const SkRect& bounds, GrColor color,
402 const GrPathUtils::QuadUVMatrix& devToUV)
403 : INHERITED(ClassID(), bounds, color)
404 , fDevToUV(devToUV)
405 , fGeometryProcessor(SkRef(gp)) {
joshualitt95964c62015-02-11 13:45:50 -0800406 }
407
408private:
joshualitt95964c62015-02-11 13:45:50 -0800409
410 struct Vertex {
411 SkPoint fPosition;
412 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
413 };
414
bsalomon342bfc22016-04-01 06:06:20 -0700415 void onPrepareDraws(Target* target) const override {
bsalomonb5238a72015-05-05 07:49:49 -0700416 QuadHelper helper;
bsalomon342bfc22016-04-01 06:06:20 -0700417 size_t vertexStride = fGeometryProcessor->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -0700418 SkASSERT(vertexStride == sizeof(Vertex));
bsalomon75398562015-08-17 12:55:38 -0700419 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
bsalomonb5238a72015-05-05 07:49:49 -0700420 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800421 return;
422 }
bsalomon342bfc22016-04-01 06:06:20 -0700423 const SkRect& bounds = this->bounds();
424 verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom,
joshualitt95964c62015-02-11 13:45:50 -0800425 sizeof(Vertex));
joshualitt95964c62015-02-11 13:45:50 -0800426 fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
bsalomon342bfc22016-04-01 06:06:20 -0700427 helper.recordDraw(target, fGeometryProcessor);
joshualitt95964c62015-02-11 13:45:50 -0800428 }
429
bsalomon342bfc22016-04-01 06:06:20 -0700430 GrPathUtils::QuadUVMatrix fDevToUV;
431 SkAutoTUnref<const GrGeometryProcessor> fGeometryProcessor;
joshualitt95964c62015-02-11 13:45:50 -0800432
433 static const int kVertsPerCubic = 4;
434 static const int kIndicesPerCubic = 6;
435
436 typedef GrTestBatch INHERITED;
437};
438
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000439/**
440 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
441 */
442class BezierQuadEffects : public GM {
443public:
444 BezierQuadEffects() {
445 this->setBGColor(0xFFFFFFFF);
446 }
447
448protected:
mtklein36352bf2015-03-25 18:17:31 -0700449 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000450 return SkString("bezier_quad_effects");
451 }
452
mtklein36352bf2015-03-25 18:17:31 -0700453 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700454 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000455 }
456
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000457
mtklein36352bf2015-03-25 18:17:31 -0700458 void onDraw(SkCanvas* canvas) override {
reed@google.com9c135db2014-03-12 18:28:35 +0000459 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -0700460 if (nullptr == rt) {
halcanary2a243382015-09-09 08:16:41 -0700461 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000462 return;
463 }
464 GrContext* context = rt->getContext();
halcanary96fcdcc2015-08-27 07:41:13 -0700465 if (nullptr == context) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000466 return;
467 }
468
joshualittf5883a62016-01-13 07:47:38 -0800469 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
470 if (!drawContext) {
471 return;
472 }
473
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000474 struct Vertex {
475 SkPoint fPosition;
476 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
477 };
478
479 static const int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000480 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000481
482 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
483 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
484 SkScalar w = SkIntToScalar(rt->width()) / numCols;
485 SkScalar h = SkIntToScalar(rt->height()) / numRows;
486 int row = 0;
487 int col = 0;
joshualitt88c23fc2015-05-13 14:18:07 -0700488 static const GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000489
490 for (int i = 0; i < kNumQuads; ++i) {
491 SkPoint baseControlPts[] = {
492 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
493 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
494 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
495 };
joshualittb0a8a372014-09-23 09:50:21 -0700496 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
497 SkAutoTUnref<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800498 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
499 gp.reset(GrQuadEffect::Create(color, SkMatrix::I(), et,
500 *context->caps(), SkMatrix::I(), false));
501 if (!gp) {
502 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000503 }
504
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000505 SkScalar x = SkScalarMul(col, w);
506 SkScalar y = SkScalarMul(row, h);
507 SkPoint controlPts[] = {
508 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
509 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
510 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
511 };
512 SkPoint chopped[5];
513 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
514
515 SkPaint ctrlPtPaint;
516 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
517 for (int i = 0; i < 3; ++i) {
518 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
519 }
520
521 SkPaint polyPaint;
522 polyPaint.setColor(0xffA0A0A0);
523 polyPaint.setStrokeWidth(0);
524 polyPaint.setStyle(SkPaint::kStroke_Style);
525 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
526
527 SkPaint choppedPtPaint;
528 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
529
530 for (int c = 0; c < cnt; ++c) {
531 SkPoint* pts = chopped + 2 * c;
532
533 for (int i = 0; i < 3; ++i) {
534 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
535 }
536
537 SkRect bounds;
538 bounds.set(pts, 3);
539
540 SkPaint boundsPaint;
541 boundsPaint.setColor(0xff808080);
542 boundsPaint.setStrokeWidth(0);
543 boundsPaint.setStyle(SkPaint::kStroke_Style);
544 canvas->drawRect(bounds, boundsPaint);
545
egdaniel8dd688b2015-01-22 10:16:09 -0800546 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800547 pipelineBuilder.setXPFactory(
548 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
joshualitt94dff152015-02-11 13:03:15 -0800549 pipelineBuilder.setRenderTarget(rt);
joshualitt3f284d72015-02-11 11:34:58 -0800550
joshualitt95964c62015-02-11 13:45:50 -0800551 GrPathUtils::QuadUVMatrix DevToUV(pts);
552
bsalomon342bfc22016-04-01 06:06:20 -0700553 SkAutoTUnref<GrDrawBatch> batch(
554 new BezierQuadTestBatch(gp, bounds, color, DevToUV));
joshualitt95964c62015-02-11 13:45:50 -0800555
robertphillips391395d2016-03-02 09:26:36 -0800556 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000557 }
558 ++col;
559 if (numCols == col) {
560 col = 0;
561 ++row;
562 }
563 }
564 }
565 }
566
567private:
568 typedef GM INHERITED;
569};
570
halcanary385fe4d2015-08-26 13:07:48 -0700571DEF_GM(return new BezierCubicEffects;)
572DEF_GM(return new BezierConicEffects;)
573DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000574}
575
576#endif