blob: d543c149c715a0c53274c89f2a2aa53a9ef2406f [file] [log] [blame]
commit-bot@chromium.org78a10782013-08-21 19:27:48 +00001
2/*
3 * Copyright 2013 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9// This test only works with the GPU backend.
10
11#include "gm.h"
12
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000013#if SK_SUPPORT_GPU
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000014
joshualitt95964c62015-02-11 13:45:50 -080015#include "GrBatchTarget.h"
16#include "GrBufferAllocPool.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000017#include "GrContext.h"
18#include "GrPathUtils.h"
19#include "GrTest.h"
joshualitt95964c62015-02-11 13:45:50 -080020#include "GrTestBatch.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000021#include "SkColorPriv.h"
22#include "SkDevice.h"
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +000023#include "SkGeometry.h"
24
25#include "effects/GrBezierEffect.h"
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000026
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000027static inline SkScalar eval_line(const SkPoint& p, const SkScalar lineEq[3], SkScalar sign) {
28 return sign * (lineEq[0] * p.fX + lineEq[1] * p.fY + lineEq[2]);
29}
30
31namespace skiagm {
joshualitt95964c62015-02-11 13:45:50 -080032
33class BezierCubicOrConicTestBatch : public GrTestBatch {
34public:
35 struct Geometry : public GrTestBatch::Geometry {
36 SkRect fBounds;
37 };
38
mtklein36352bf2015-03-25 18:17:31 -070039 const char* name() const override { return "BezierCubicOrConicTestBatch"; }
joshualitt95964c62015-02-11 13:45:50 -080040
41 static GrBatch* Create(const GrGeometryProcessor* gp, const Geometry& geo,
42 const SkScalar klmEqs[9], SkScalar sign) {
43 return SkNEW_ARGS(BezierCubicOrConicTestBatch, (gp, geo, klmEqs, sign));
44 }
45
46private:
47 BezierCubicOrConicTestBatch(const GrGeometryProcessor* gp, const Geometry& geo,
48 const SkScalar klmEqs[9], SkScalar sign)
joshualitt99c7c072015-05-01 13:43:30 -070049 : INHERITED(gp, geo.fBounds) {
joshualitt95964c62015-02-11 13:45:50 -080050 for (int i = 0; i < 9; i++) {
51 fKlmEqs[i] = klmEqs[i];
52 }
53
54 fGeometry = geo;
55 fSign = sign;
56 }
57
58 struct Vertex {
59 SkPoint fPosition;
60 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
61 };
62
mtklein36352bf2015-03-25 18:17:31 -070063 Geometry* geoData(int index) override {
joshualitt95964c62015-02-11 13:45:50 -080064 SkASSERT(0 == index);
65 return &fGeometry;
66 }
67
mtklein36352bf2015-03-25 18:17:31 -070068 void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
bsalomonb5238a72015-05-05 07:49:49 -070069 QuadHelper helper;
bsalomoned0bcad2015-05-04 10:36:42 -070070 size_t vertexStride = this->geometryProcessor()->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -070071 SkASSERT(vertexStride == sizeof(Vertex));
72 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(batchTarget, vertexStride, 1));
73 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -080074 return;
75 }
76
joshualitt95964c62015-02-11 13:45:50 -080077 verts[0].fPosition.setRectFan(fGeometry.fBounds.fLeft, fGeometry.fBounds.fTop,
78 fGeometry.fBounds.fRight, fGeometry.fBounds.fBottom,
79 sizeof(Vertex));
80 for (int v = 0; v < 4; ++v) {
81 verts[v].fKLM[0] = eval_line(verts[v].fPosition, fKlmEqs + 0, fSign);
82 verts[v].fKLM[1] = eval_line(verts[v].fPosition, fKlmEqs + 3, fSign);
83 verts[v].fKLM[2] = eval_line(verts[v].fPosition, fKlmEqs + 6, 1.f);
84 }
bsalomonb5238a72015-05-05 07:49:49 -070085 helper.issueDraws(batchTarget);
joshualitt95964c62015-02-11 13:45:50 -080086 }
87
88 Geometry fGeometry;
89 SkScalar fKlmEqs[9];
90 SkScalar fSign;
91
92 static const int kVertsPerCubic = 4;
93 static const int kIndicesPerCubic = 6;
94
95 typedef GrTestBatch INHERITED;
96};
97
commit-bot@chromium.org78a10782013-08-21 19:27:48 +000098/**
99 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
100 */
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000101class BezierCubicEffects : public GM {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000102public:
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000103 BezierCubicEffects() {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000104 this->setBGColor(0xFFFFFFFF);
105 }
106
107protected:
mtklein36352bf2015-03-25 18:17:31 -0700108 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000109 return SkString("bezier_cubic_effects");
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000110 }
111
mtklein36352bf2015-03-25 18:17:31 -0700112 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700113 return SkISize::Make(800, 800);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000114 }
115
mtklein36352bf2015-03-25 18:17:31 -0700116 void onDraw(SkCanvas* canvas) override {
reed@google.com9c135db2014-03-12 18:28:35 +0000117 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000118 if (NULL == rt) {
bsalomonb62da802015-01-31 07:51:14 -0800119 this->drawGpuOnlyMessage(canvas);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000120 return;
121 }
122 GrContext* context = rt->getContext();
123 if (NULL == context) {
124 return;
125 }
126
127 struct Vertex {
128 SkPoint fPosition;
129 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
130 };
131
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000132 static const int kNumCubics = 15;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000133 SkRandom rand;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000134
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000135 // Mult by 3 for each edge effect type
136 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
137 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000138 SkScalar w = SkIntToScalar(rt->width()) / numCols;
139 SkScalar h = SkIntToScalar(rt->height()) / numRows;
140 int row = 0;
141 int col = 0;
142
143 for (int i = 0; i < kNumCubics; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000144 SkPoint baseControlPts[] = {
145 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
146 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
147 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
148 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000149 };
joshualittb0a8a372014-09-23 09:50:21 -0700150 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
151 SkAutoTUnref<GrGeometryProcessor> gp;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000152 { // scope to contain GrTestTarget
153 GrTestTarget tt;
154 context->getTestTarget(&tt);
155 if (NULL == tt.target()) {
156 continue;
157 }
joshualittb0a8a372014-09-23 09:50:21 -0700158 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
joshualitt8059eb92014-12-29 15:10:07 -0800159 gp.reset(GrCubicEffect::Create(0xff000000, SkMatrix::I(), et,
160 *tt.target()->caps()));
joshualittb0a8a372014-09-23 09:50:21 -0700161 if (!gp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000162 continue;
163 }
164 }
165
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000166 SkScalar x = SkScalarMul(col, w);
167 SkScalar y = SkScalarMul(row, h);
168 SkPoint controlPts[] = {
169 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
170 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
171 {x + baseControlPts[2].fX, y + baseControlPts[2].fY},
172 {x + baseControlPts[3].fX, y + baseControlPts[3].fY}
173 };
174 SkPoint chopped[10];
175 SkScalar klmEqs[9];
176 SkScalar klmSigns[3];
177 int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
178 chopped,
179 klmEqs,
180 klmSigns);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000181
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000182 SkPaint ctrlPtPaint;
183 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000184 for (int i = 0; i < 4; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000185 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000186 }
187
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000188 SkPaint polyPaint;
189 polyPaint.setColor(0xffA0A0A0);
190 polyPaint.setStrokeWidth(0);
191 polyPaint.setStyle(SkPaint::kStroke_Style);
192 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000193
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000194 SkPaint choppedPtPaint;
195 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000196
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000197 for (int c = 0; c < cnt; ++c) {
198 SkPoint* pts = chopped + 3 * c;
199
200 for (int i = 0; i < 4; ++i) {
201 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
202 }
203
204 SkRect bounds;
205 bounds.set(pts, 4);
206
207 SkPaint boundsPaint;
208 boundsPaint.setColor(0xff808080);
209 boundsPaint.setStrokeWidth(0);
210 boundsPaint.setStyle(SkPaint::kStroke_Style);
211 canvas->drawRect(bounds, boundsPaint);
212
joshualitt50408ad2014-11-03 12:31:14 -0800213 GrTestTarget tt;
214 context->getTestTarget(&tt);
215 SkASSERT(tt.target());
216
egdaniel8dd688b2015-01-22 10:16:09 -0800217 GrPipelineBuilder pipelineBuilder;
egdaniel8dd688b2015-01-22 10:16:09 -0800218 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000219
joshualitt95964c62015-02-11 13:45:50 -0800220 BezierCubicOrConicTestBatch::Geometry geometry;
221 geometry.fColor = gp->color();
222 geometry.fBounds = bounds;
223
joshualitt44701df2015-02-23 14:44:57 -0800224 SkAutoTUnref<GrBatch> batch(
225 BezierCubicOrConicTestBatch::Create(gp, geometry, klmEqs, klmSigns[c]));
joshualitt95964c62015-02-11 13:45:50 -0800226
joshualitt99c7c072015-05-01 13:43:30 -0700227 tt.target()->drawBatch(&pipelineBuilder, batch);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000228 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000229 ++col;
230 if (numCols == col) {
231 col = 0;
232 ++row;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000233 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000234 }
235 }
236 }
237
238private:
239 typedef GM INHERITED;
240};
241
242//////////////////////////////////////////////////////////////////////////////
243
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000244/**
245 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
246 */
247class BezierConicEffects : public GM {
248public:
249 BezierConicEffects() {
250 this->setBGColor(0xFFFFFFFF);
251 }
252
253protected:
mtklein36352bf2015-03-25 18:17:31 -0700254 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000255 return SkString("bezier_conic_effects");
256 }
257
mtklein36352bf2015-03-25 18:17:31 -0700258 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700259 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000260 }
261
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000262
mtklein36352bf2015-03-25 18:17:31 -0700263 void onDraw(SkCanvas* canvas) override {
reed@google.com9c135db2014-03-12 18:28:35 +0000264 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000265 if (NULL == rt) {
bsalomonb62da802015-01-31 07:51:14 -0800266 this->drawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000267 return;
268 }
269 GrContext* context = rt->getContext();
270 if (NULL == context) {
271 return;
272 }
273
274 struct Vertex {
275 SkPoint fPosition;
276 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
277 };
278
279 static const int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000280 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000281
282 // Mult by 3 for each edge effect type
283 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
284 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
285 SkScalar w = SkIntToScalar(rt->width()) / numCols;
286 SkScalar h = SkIntToScalar(rt->height()) / numRows;
287 int row = 0;
288 int col = 0;
289
290 for (int i = 0; i < kNumConics; ++i) {
291 SkPoint baseControlPts[] = {
292 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
293 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
294 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
295 };
296 SkScalar weight = rand.nextRangeF(0.f, 2.f);
joshualittb0a8a372014-09-23 09:50:21 -0700297 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
298 SkAutoTUnref<GrGeometryProcessor> gp;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000299 { // scope to contain GrTestTarget
300 GrTestTarget tt;
301 context->getTestTarget(&tt);
302 if (NULL == tt.target()) {
303 continue;
304 }
joshualittb0a8a372014-09-23 09:50:21 -0700305 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
joshualitt8059eb92014-12-29 15:10:07 -0800306 gp.reset(GrConicEffect::Create(0xff000000, SkMatrix::I(), et,
307 *tt.target()->caps(), SkMatrix::I()));
joshualittb0a8a372014-09-23 09:50:21 -0700308 if (!gp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000309 continue;
310 }
311 }
312
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000313 SkScalar x = SkScalarMul(col, w);
314 SkScalar y = SkScalarMul(row, h);
315 SkPoint controlPts[] = {
316 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
317 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
318 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
319 };
320 SkConic dst[4];
321 SkScalar klmEqs[9];
322 int cnt = chop_conic(controlPts, dst, weight);
323 GrPathUtils::getConicKLM(controlPts, weight, klmEqs);
324
325 SkPaint ctrlPtPaint;
326 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
327 for (int i = 0; i < 3; ++i) {
328 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
329 }
330
331 SkPaint polyPaint;
332 polyPaint.setColor(0xffA0A0A0);
333 polyPaint.setStrokeWidth(0);
334 polyPaint.setStyle(SkPaint::kStroke_Style);
335 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
336
337 SkPaint choppedPtPaint;
338 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
339
340 for (int c = 0; c < cnt; ++c) {
341 SkPoint* pts = dst[c].fPts;
342 for (int i = 0; i < 3; ++i) {
343 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
344 }
345
346 SkRect bounds;
347 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
348 //bounds.set(bPts, 2);
349 bounds.set(pts, 3);
350
351 SkPaint boundsPaint;
352 boundsPaint.setColor(0xff808080);
353 boundsPaint.setStrokeWidth(0);
354 boundsPaint.setStyle(SkPaint::kStroke_Style);
355 canvas->drawRect(bounds, boundsPaint);
356
joshualitt50408ad2014-11-03 12:31:14 -0800357 GrTestTarget tt;
358 context->getTestTarget(&tt);
359 SkASSERT(tt.target());
360
egdaniel8dd688b2015-01-22 10:16:09 -0800361 GrPipelineBuilder pipelineBuilder;
egdaniel8dd688b2015-01-22 10:16:09 -0800362 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000363
joshualitt95964c62015-02-11 13:45:50 -0800364 BezierCubicOrConicTestBatch::Geometry geometry;
365 geometry.fColor = gp->color();
366 geometry.fBounds = bounds;
367
joshualitt44701df2015-02-23 14:44:57 -0800368 SkAutoTUnref<GrBatch> batch(
369 BezierCubicOrConicTestBatch::Create(gp, geometry, klmEqs, 1.f));
joshualitt95964c62015-02-11 13:45:50 -0800370
joshualitt99c7c072015-05-01 13:43:30 -0700371 tt.target()->drawBatch(&pipelineBuilder, batch);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000372 }
373 ++col;
374 if (numCols == col) {
375 col = 0;
376 ++row;
377 }
378 }
379 }
380 }
381
382private:
383 // Uses the max curvature function for quads to estimate
384 // where to chop the conic. If the max curvature is not
385 // found along the curve segment it will return 1 and
386 // dst[0] is the original conic. If it returns 2 the dst[0]
387 // and dst[1] are the two new conics.
388 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
389 SkScalar t = SkFindQuadMaxCurvature(src);
390 if (t == 0) {
391 if (dst) {
392 dst[0].set(src, weight);
393 }
394 return 1;
395 } else {
396 if (dst) {
397 SkConic conic;
398 conic.set(src, weight);
399 conic.chopAt(t, dst);
400 }
401 return 2;
402 }
403 }
404
405 // Calls split_conic on the entire conic and then once more on each subsection.
406 // Most cases will result in either 1 conic (chop point is not within t range)
407 // or 3 points (split once and then one subsection is split again).
408 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
409 SkConic dstTemp[2];
410 int conicCnt = split_conic(src, dstTemp, weight);
411 if (2 == conicCnt) {
412 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
413 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
414 } else {
415 dst[0] = dstTemp[0];
416 }
417 return conicCnt;
418 }
419
420 typedef GM INHERITED;
421};
422
423//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800424
425class BezierQuadTestBatch : public GrTestBatch {
426public:
427 struct Geometry : public GrTestBatch::Geometry {
428 SkRect fBounds;
429 };
430
mtklein36352bf2015-03-25 18:17:31 -0700431 const char* name() const override { return "BezierQuadTestBatch"; }
joshualitt95964c62015-02-11 13:45:50 -0800432
433 static GrBatch* Create(const GrGeometryProcessor* gp, const Geometry& geo,
434 const GrPathUtils::QuadUVMatrix& devToUV) {
435 return SkNEW_ARGS(BezierQuadTestBatch, (gp, geo, devToUV));
436 }
437
438private:
439 BezierQuadTestBatch(const GrGeometryProcessor* gp, const Geometry& geo,
440 const GrPathUtils::QuadUVMatrix& devToUV)
joshualitt99c7c072015-05-01 13:43:30 -0700441 : INHERITED(gp, geo.fBounds)
joshualitt95964c62015-02-11 13:45:50 -0800442 , fGeometry(geo)
443 , fDevToUV(devToUV) {
444 }
445
446 struct Vertex {
447 SkPoint fPosition;
448 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
449 };
450
mtklein36352bf2015-03-25 18:17:31 -0700451 Geometry* geoData(int index) override {
joshualitt95964c62015-02-11 13:45:50 -0800452 SkASSERT(0 == index);
453 return &fGeometry;
454 }
455
mtklein36352bf2015-03-25 18:17:31 -0700456 void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
bsalomonb5238a72015-05-05 07:49:49 -0700457 QuadHelper helper;
bsalomoned0bcad2015-05-04 10:36:42 -0700458 size_t vertexStride = this->geometryProcessor()->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -0700459 SkASSERT(vertexStride == sizeof(Vertex));
460 GrDrawTarget::DrawInfo drawInfo;
461 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(batchTarget, vertexStride, 1));
462 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800463 return;
464 }
joshualitt95964c62015-02-11 13:45:50 -0800465 verts[0].fPosition.setRectFan(fGeometry.fBounds.fLeft, fGeometry.fBounds.fTop,
466 fGeometry.fBounds.fRight, fGeometry.fBounds.fBottom,
467 sizeof(Vertex));
joshualitt95964c62015-02-11 13:45:50 -0800468 fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
bsalomonb5238a72015-05-05 07:49:49 -0700469 helper.issueDraws(batchTarget);
joshualitt95964c62015-02-11 13:45:50 -0800470 }
471
472 Geometry fGeometry;
473 GrPathUtils::QuadUVMatrix fDevToUV;
474
475 static const int kVertsPerCubic = 4;
476 static const int kIndicesPerCubic = 6;
477
478 typedef GrTestBatch INHERITED;
479};
480
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000481/**
482 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
483 */
484class BezierQuadEffects : public GM {
485public:
486 BezierQuadEffects() {
487 this->setBGColor(0xFFFFFFFF);
488 }
489
490protected:
mtklein36352bf2015-03-25 18:17:31 -0700491 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000492 return SkString("bezier_quad_effects");
493 }
494
mtklein36352bf2015-03-25 18:17:31 -0700495 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700496 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000497 }
498
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000499
mtklein36352bf2015-03-25 18:17:31 -0700500 void onDraw(SkCanvas* canvas) override {
reed@google.com9c135db2014-03-12 18:28:35 +0000501 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000502 if (NULL == rt) {
bsalomonb62da802015-01-31 07:51:14 -0800503 this->drawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000504 return;
505 }
506 GrContext* context = rt->getContext();
507 if (NULL == context) {
508 return;
509 }
510
511 struct Vertex {
512 SkPoint fPosition;
513 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
514 };
515
516 static const int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000517 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000518
519 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
520 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
521 SkScalar w = SkIntToScalar(rt->width()) / numCols;
522 SkScalar h = SkIntToScalar(rt->height()) / numRows;
523 int row = 0;
524 int col = 0;
525
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) {
533 SkAutoTUnref<GrGeometryProcessor> gp;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000534 { // scope to contain GrTestTarget
535 GrTestTarget tt;
536 context->getTestTarget(&tt);
537 if (NULL == tt.target()) {
538 continue;
539 }
joshualittb0a8a372014-09-23 09:50:21 -0700540 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
joshualitt8059eb92014-12-29 15:10:07 -0800541 gp.reset(GrQuadEffect::Create(0xff000000, SkMatrix::I(), et,
542 *tt.target()->caps(), SkMatrix::I()));
joshualittb0a8a372014-09-23 09:50:21 -0700543 if (!gp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000544 continue;
545 }
546 }
547
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000548 SkScalar x = SkScalarMul(col, w);
549 SkScalar y = SkScalarMul(row, h);
550 SkPoint controlPts[] = {
551 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
552 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
553 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
554 };
555 SkPoint chopped[5];
556 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
557
558 SkPaint ctrlPtPaint;
559 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
560 for (int i = 0; i < 3; ++i) {
561 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
562 }
563
564 SkPaint polyPaint;
565 polyPaint.setColor(0xffA0A0A0);
566 polyPaint.setStrokeWidth(0);
567 polyPaint.setStyle(SkPaint::kStroke_Style);
568 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
569
570 SkPaint choppedPtPaint;
571 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
572
573 for (int c = 0; c < cnt; ++c) {
574 SkPoint* pts = chopped + 2 * c;
575
576 for (int i = 0; i < 3; ++i) {
577 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
578 }
579
580 SkRect bounds;
581 bounds.set(pts, 3);
582
583 SkPaint boundsPaint;
584 boundsPaint.setColor(0xff808080);
585 boundsPaint.setStrokeWidth(0);
586 boundsPaint.setStyle(SkPaint::kStroke_Style);
587 canvas->drawRect(bounds, boundsPaint);
588
joshualitt50408ad2014-11-03 12:31:14 -0800589 GrTestTarget tt;
590 context->getTestTarget(&tt);
591 SkASSERT(tt.target());
592
egdaniel8dd688b2015-01-22 10:16:09 -0800593 GrPipelineBuilder pipelineBuilder;
joshualitt94dff152015-02-11 13:03:15 -0800594 pipelineBuilder.setRenderTarget(rt);
joshualitt3f284d72015-02-11 11:34:58 -0800595
joshualitt95964c62015-02-11 13:45:50 -0800596 GrPathUtils::QuadUVMatrix DevToUV(pts);
597
598 BezierQuadTestBatch::Geometry geometry;
599 geometry.fColor = gp->color();
600 geometry.fBounds = bounds;
601
602 SkAutoTUnref<GrBatch> batch(BezierQuadTestBatch::Create(gp, geometry, DevToUV));
603
joshualitt99c7c072015-05-01 13:43:30 -0700604 tt.target()->drawBatch(&pipelineBuilder, batch);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000605 }
606 ++col;
607 if (numCols == col) {
608 col = 0;
609 ++row;
610 }
611 }
612 }
613 }
614
615private:
616 typedef GM INHERITED;
617};
618
619DEF_GM( return SkNEW(BezierCubicEffects); )
620DEF_GM( return SkNEW(BezierConicEffects); )
621DEF_GM( return SkNEW(BezierQuadEffects); )
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000622
623}
624
625#endif