blob: 578a597ce51ce4f6808ea658e760d4aba456545a [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
joshualitt3f284d72015-02-11 11:34:58 -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"
joshualitt3f284d72015-02-11 11:34:58 -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 {
joshualitt3f284d72015-02-11 11:34:58 -080032
33class BezierCubicOrConicTestBatch : public GrTestBatch {
34public:
35 struct Geometry : public GrTestBatch::Geometry {
36 SkRect fBounds;
37 };
38
39 const char* name() const SK_OVERRIDE { return "BezierCubicOrConicTestBatch"; }
40
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)
49 : INHERITED(gp) {
50 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
63 Geometry* geoData(int index) SK_OVERRIDE {
64 SkASSERT(0 == index);
65 return &fGeometry;
66 }
67
68 void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) SK_OVERRIDE {
69 size_t vertexStride = this->geometryProcessor()->getVertexStride();
70
71 const GrVertexBuffer* vertexBuffer;
72 int firstVertex;
73
74 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
75 kVertsPerCubic,
76 &vertexBuffer,
77 &firstVertex);
78
79 SkASSERT(vertexStride == sizeof(Vertex));
80 Vertex* verts = reinterpret_cast<Vertex*>(vertices);
81
82 verts[0].fPosition.setRectFan(fGeometry.fBounds.fLeft, fGeometry.fBounds.fTop,
83 fGeometry.fBounds.fRight, fGeometry.fBounds.fBottom,
84 sizeof(Vertex));
85 for (int v = 0; v < 4; ++v) {
86 verts[v].fKLM[0] = eval_line(verts[v].fPosition, fKlmEqs + 0, fSign);
87 verts[v].fKLM[1] = eval_line(verts[v].fPosition, fKlmEqs + 3, fSign);
88 verts[v].fKLM[2] = eval_line(verts[v].fPosition, fKlmEqs + 6, 1.f);
89 }
90
91 GrDrawTarget::DrawInfo drawInfo;
92 drawInfo.setPrimitiveType(kTriangleFan_GrPrimitiveType);
93 drawInfo.setVertexBuffer(vertexBuffer);
94 drawInfo.setStartVertex(firstVertex);
95 drawInfo.setVertexCount(kVertsPerCubic);
96 drawInfo.setStartIndex(0);
97 drawInfo.setIndexCount(kIndicesPerCubic);
98 drawInfo.setIndexBuffer(batchTarget->quadIndexBuffer());
99 batchTarget->draw(drawInfo);
100 }
101
102 Geometry fGeometry;
103 SkScalar fKlmEqs[9];
104 SkScalar fSign;
105
106 static const int kVertsPerCubic = 4;
107 static const int kIndicesPerCubic = 6;
108
109 typedef GrTestBatch INHERITED;
110};
111
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000112/**
113 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
114 */
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000115class BezierCubicEffects : public GM {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000116public:
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000117 BezierCubicEffects() {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000118 this->setBGColor(0xFFFFFFFF);
119 }
120
121protected:
mtklein72c9faa2015-01-09 10:06:39 -0800122 SkString onShortName() SK_OVERRIDE {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000123 return SkString("bezier_cubic_effects");
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000124 }
125
mtklein72c9faa2015-01-09 10:06:39 -0800126 SkISize onISize() SK_OVERRIDE {
tfarinaf5393182014-06-09 23:59:03 -0700127 return SkISize::Make(800, 800);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000128 }
129
mtklein72c9faa2015-01-09 10:06:39 -0800130 void onDraw(SkCanvas* canvas) SK_OVERRIDE {
reed@google.com9c135db2014-03-12 18:28:35 +0000131 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000132 if (NULL == rt) {
bsalomonb62da802015-01-31 07:51:14 -0800133 this->drawGpuOnlyMessage(canvas);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000134 return;
135 }
136 GrContext* context = rt->getContext();
137 if (NULL == context) {
138 return;
139 }
140
141 struct Vertex {
142 SkPoint fPosition;
143 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
144 };
145
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000146 static const int kNumCubics = 15;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000147 SkRandom rand;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000148
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000149 // Mult by 3 for each edge effect type
150 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
151 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000152 SkScalar w = SkIntToScalar(rt->width()) / numCols;
153 SkScalar h = SkIntToScalar(rt->height()) / numRows;
154 int row = 0;
155 int col = 0;
156
157 for (int i = 0; i < kNumCubics; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000158 SkPoint baseControlPts[] = {
159 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
160 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
161 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
162 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000163 };
joshualittb0a8a372014-09-23 09:50:21 -0700164 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
165 SkAutoTUnref<GrGeometryProcessor> gp;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000166 { // scope to contain GrTestTarget
167 GrTestTarget tt;
168 context->getTestTarget(&tt);
169 if (NULL == tt.target()) {
170 continue;
171 }
joshualittb0a8a372014-09-23 09:50:21 -0700172 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
joshualitt8059eb92014-12-29 15:10:07 -0800173 gp.reset(GrCubicEffect::Create(0xff000000, SkMatrix::I(), et,
174 *tt.target()->caps()));
joshualittb0a8a372014-09-23 09:50:21 -0700175 if (!gp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000176 continue;
177 }
178 }
179
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000180 SkScalar x = SkScalarMul(col, w);
181 SkScalar y = SkScalarMul(row, h);
182 SkPoint controlPts[] = {
183 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
184 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
185 {x + baseControlPts[2].fX, y + baseControlPts[2].fY},
186 {x + baseControlPts[3].fX, y + baseControlPts[3].fY}
187 };
188 SkPoint chopped[10];
189 SkScalar klmEqs[9];
190 SkScalar klmSigns[3];
191 int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
192 chopped,
193 klmEqs,
194 klmSigns);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000195
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000196 SkPaint ctrlPtPaint;
197 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000198 for (int i = 0; i < 4; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000199 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000200 }
201
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000202 SkPaint polyPaint;
203 polyPaint.setColor(0xffA0A0A0);
204 polyPaint.setStrokeWidth(0);
205 polyPaint.setStyle(SkPaint::kStroke_Style);
206 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000207
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000208 SkPaint choppedPtPaint;
209 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000210
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000211 for (int c = 0; c < cnt; ++c) {
212 SkPoint* pts = chopped + 3 * c;
213
214 for (int i = 0; i < 4; ++i) {
215 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
216 }
217
218 SkRect bounds;
219 bounds.set(pts, 4);
220
221 SkPaint boundsPaint;
222 boundsPaint.setColor(0xff808080);
223 boundsPaint.setStrokeWidth(0);
224 boundsPaint.setStyle(SkPaint::kStroke_Style);
225 canvas->drawRect(bounds, boundsPaint);
226
joshualitt50408ad2014-11-03 12:31:14 -0800227 GrTestTarget tt;
228 context->getTestTarget(&tt);
229 SkASSERT(tt.target());
230
egdaniel8dd688b2015-01-22 10:16:09 -0800231 GrPipelineBuilder pipelineBuilder;
egdaniel8dd688b2015-01-22 10:16:09 -0800232 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000233
joshualitt3f284d72015-02-11 11:34:58 -0800234 BezierCubicOrConicTestBatch::Geometry geometry;
235 geometry.fColor = gp->color();
236 geometry.fBounds = bounds;
237
238 SkAutoTUnref<GrBatch> batch(BezierCubicOrConicTestBatch::Create(gp, geometry, klmEqs,
239 klmSigns[c]));
240
241 tt.target()->drawBatch(&pipelineBuilder, batch, NULL);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000242 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000243 ++col;
244 if (numCols == col) {
245 col = 0;
246 ++row;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000247 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000248 }
249 }
250 }
251
252private:
253 typedef GM INHERITED;
254};
255
256//////////////////////////////////////////////////////////////////////////////
257
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000258/**
259 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
260 */
261class BezierConicEffects : public GM {
262public:
263 BezierConicEffects() {
264 this->setBGColor(0xFFFFFFFF);
265 }
266
267protected:
mtklein72c9faa2015-01-09 10:06:39 -0800268 SkString onShortName() SK_OVERRIDE {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000269 return SkString("bezier_conic_effects");
270 }
271
mtklein72c9faa2015-01-09 10:06:39 -0800272 SkISize onISize() SK_OVERRIDE {
tfarinaf5393182014-06-09 23:59:03 -0700273 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000274 }
275
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000276
mtklein72c9faa2015-01-09 10:06:39 -0800277 void onDraw(SkCanvas* canvas) SK_OVERRIDE {
reed@google.com9c135db2014-03-12 18:28:35 +0000278 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000279 if (NULL == rt) {
bsalomonb62da802015-01-31 07:51:14 -0800280 this->drawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000281 return;
282 }
283 GrContext* context = rt->getContext();
284 if (NULL == context) {
285 return;
286 }
287
288 struct Vertex {
289 SkPoint fPosition;
290 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
291 };
292
293 static const int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000294 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000295
296 // Mult by 3 for each edge effect type
297 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
298 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
299 SkScalar w = SkIntToScalar(rt->width()) / numCols;
300 SkScalar h = SkIntToScalar(rt->height()) / numRows;
301 int row = 0;
302 int col = 0;
303
304 for (int i = 0; i < kNumConics; ++i) {
305 SkPoint baseControlPts[] = {
306 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
307 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
308 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
309 };
310 SkScalar weight = rand.nextRangeF(0.f, 2.f);
joshualittb0a8a372014-09-23 09:50:21 -0700311 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
312 SkAutoTUnref<GrGeometryProcessor> gp;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000313 { // scope to contain GrTestTarget
314 GrTestTarget tt;
315 context->getTestTarget(&tt);
316 if (NULL == tt.target()) {
317 continue;
318 }
joshualittb0a8a372014-09-23 09:50:21 -0700319 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
joshualitt8059eb92014-12-29 15:10:07 -0800320 gp.reset(GrConicEffect::Create(0xff000000, SkMatrix::I(), et,
321 *tt.target()->caps(), SkMatrix::I()));
joshualittb0a8a372014-09-23 09:50:21 -0700322 if (!gp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000323 continue;
324 }
325 }
326
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000327 SkScalar x = SkScalarMul(col, w);
328 SkScalar y = SkScalarMul(row, h);
329 SkPoint controlPts[] = {
330 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
331 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
332 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
333 };
334 SkConic dst[4];
335 SkScalar klmEqs[9];
336 int cnt = chop_conic(controlPts, dst, weight);
337 GrPathUtils::getConicKLM(controlPts, weight, klmEqs);
338
339 SkPaint ctrlPtPaint;
340 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
341 for (int i = 0; i < 3; ++i) {
342 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
343 }
344
345 SkPaint polyPaint;
346 polyPaint.setColor(0xffA0A0A0);
347 polyPaint.setStrokeWidth(0);
348 polyPaint.setStyle(SkPaint::kStroke_Style);
349 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
350
351 SkPaint choppedPtPaint;
352 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
353
354 for (int c = 0; c < cnt; ++c) {
355 SkPoint* pts = dst[c].fPts;
356 for (int i = 0; i < 3; ++i) {
357 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
358 }
359
360 SkRect bounds;
361 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
362 //bounds.set(bPts, 2);
363 bounds.set(pts, 3);
364
365 SkPaint boundsPaint;
366 boundsPaint.setColor(0xff808080);
367 boundsPaint.setStrokeWidth(0);
368 boundsPaint.setStyle(SkPaint::kStroke_Style);
369 canvas->drawRect(bounds, boundsPaint);
370
joshualitt50408ad2014-11-03 12:31:14 -0800371 GrTestTarget tt;
372 context->getTestTarget(&tt);
373 SkASSERT(tt.target());
374
egdaniel8dd688b2015-01-22 10:16:09 -0800375 GrPipelineBuilder pipelineBuilder;
egdaniel8dd688b2015-01-22 10:16:09 -0800376 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000377
joshualitt3f284d72015-02-11 11:34:58 -0800378 BezierCubicOrConicTestBatch::Geometry geometry;
379 geometry.fColor = gp->color();
380 geometry.fBounds = bounds;
381
382 SkAutoTUnref<GrBatch> batch(BezierCubicOrConicTestBatch::Create(gp, geometry, klmEqs,
383 1.f));
384
385 tt.target()->drawBatch(&pipelineBuilder, batch, NULL);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000386 }
387 ++col;
388 if (numCols == col) {
389 col = 0;
390 ++row;
391 }
392 }
393 }
394 }
395
396private:
397 // Uses the max curvature function for quads to estimate
398 // where to chop the conic. If the max curvature is not
399 // found along the curve segment it will return 1 and
400 // dst[0] is the original conic. If it returns 2 the dst[0]
401 // and dst[1] are the two new conics.
402 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
403 SkScalar t = SkFindQuadMaxCurvature(src);
404 if (t == 0) {
405 if (dst) {
406 dst[0].set(src, weight);
407 }
408 return 1;
409 } else {
410 if (dst) {
411 SkConic conic;
412 conic.set(src, weight);
413 conic.chopAt(t, dst);
414 }
415 return 2;
416 }
417 }
418
419 // Calls split_conic on the entire conic and then once more on each subsection.
420 // Most cases will result in either 1 conic (chop point is not within t range)
421 // or 3 points (split once and then one subsection is split again).
422 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
423 SkConic dstTemp[2];
424 int conicCnt = split_conic(src, dstTemp, weight);
425 if (2 == conicCnt) {
426 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
427 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
428 } else {
429 dst[0] = dstTemp[0];
430 }
431 return conicCnt;
432 }
433
434 typedef GM INHERITED;
435};
436
437//////////////////////////////////////////////////////////////////////////////
joshualitt3f284d72015-02-11 11:34:58 -0800438
439class BezierQuadTestBatch : public GrTestBatch {
440public:
441 struct Geometry : public GrTestBatch::Geometry {
442 SkRect fBounds;
443 };
444
445 const char* name() const SK_OVERRIDE { return "BezierQuadTestBatch"; }
446
447 static GrBatch* Create(const GrGeometryProcessor* gp, const Geometry& geo,
448 const GrPathUtils::QuadUVMatrix& devToUV) {
449 return SkNEW_ARGS(BezierQuadTestBatch, (gp, geo, devToUV));
450 }
451
452private:
453 BezierQuadTestBatch(const GrGeometryProcessor* gp, const Geometry& geo,
454 const GrPathUtils::QuadUVMatrix& devToUV)
455 : INHERITED(gp)
456 , fGeometry(geo)
457 , fDevToUV(devToUV) {
458 }
459
460 struct Vertex {
461 SkPoint fPosition;
462 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
463 };
464
465 Geometry* geoData(int index) SK_OVERRIDE {
466 SkASSERT(0 == index);
467 return &fGeometry;
468 }
469
470 void onGenerateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) SK_OVERRIDE {
471 size_t vertexStride = this->geometryProcessor()->getVertexStride();
472
473 const GrVertexBuffer* vertexBuffer;
474 int firstVertex;
475
476 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride,
477 kVertsPerCubic,
478 &vertexBuffer,
479 &firstVertex);
480
481 SkASSERT(vertexStride == sizeof(Vertex));
482 Vertex* verts = reinterpret_cast<Vertex*>(vertices);
483
484 verts[0].fPosition.setRectFan(fGeometry.fBounds.fLeft, fGeometry.fBounds.fTop,
485 fGeometry.fBounds.fRight, fGeometry.fBounds.fBottom,
486 sizeof(Vertex));
487
488 fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
489
490
491 GrDrawTarget::DrawInfo drawInfo;
492 drawInfo.setPrimitiveType(kTriangles_GrPrimitiveType);
493 drawInfo.setVertexBuffer(vertexBuffer);
494 drawInfo.setStartVertex(firstVertex);
495 drawInfo.setVertexCount(kVertsPerCubic);
496 drawInfo.setStartIndex(0);
497 drawInfo.setIndexCount(kIndicesPerCubic);
498 drawInfo.setIndexBuffer(batchTarget->quadIndexBuffer());
499 batchTarget->draw(drawInfo);
500 }
501
502 Geometry fGeometry;
503 GrPathUtils::QuadUVMatrix fDevToUV;
504
505 static const int kVertsPerCubic = 4;
506 static const int kIndicesPerCubic = 6;
507
508 typedef GrTestBatch INHERITED;
509};
510
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000511/**
512 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
513 */
514class BezierQuadEffects : public GM {
515public:
516 BezierQuadEffects() {
517 this->setBGColor(0xFFFFFFFF);
518 }
519
520protected:
mtklein72c9faa2015-01-09 10:06:39 -0800521 SkString onShortName() SK_OVERRIDE {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000522 return SkString("bezier_quad_effects");
523 }
524
mtklein72c9faa2015-01-09 10:06:39 -0800525 SkISize onISize() SK_OVERRIDE {
tfarinaf5393182014-06-09 23:59:03 -0700526 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000527 }
528
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000529
mtklein72c9faa2015-01-09 10:06:39 -0800530 void onDraw(SkCanvas* canvas) SK_OVERRIDE {
reed@google.com9c135db2014-03-12 18:28:35 +0000531 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000532 if (NULL == rt) {
bsalomonb62da802015-01-31 07:51:14 -0800533 this->drawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000534 return;
535 }
536 GrContext* context = rt->getContext();
537 if (NULL == context) {
538 return;
539 }
540
541 struct Vertex {
542 SkPoint fPosition;
543 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
544 };
545
546 static const int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000547 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000548
549 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
550 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
551 SkScalar w = SkIntToScalar(rt->width()) / numCols;
552 SkScalar h = SkIntToScalar(rt->height()) / numRows;
553 int row = 0;
554 int col = 0;
555
556 for (int i = 0; i < kNumQuads; ++i) {
557 SkPoint baseControlPts[] = {
558 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
559 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
560 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
561 };
joshualittb0a8a372014-09-23 09:50:21 -0700562 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
563 SkAutoTUnref<GrGeometryProcessor> gp;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000564 { // scope to contain GrTestTarget
565 GrTestTarget tt;
566 context->getTestTarget(&tt);
567 if (NULL == tt.target()) {
568 continue;
569 }
joshualittb0a8a372014-09-23 09:50:21 -0700570 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
joshualitt8059eb92014-12-29 15:10:07 -0800571 gp.reset(GrQuadEffect::Create(0xff000000, SkMatrix::I(), et,
572 *tt.target()->caps(), SkMatrix::I()));
joshualittb0a8a372014-09-23 09:50:21 -0700573 if (!gp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000574 continue;
575 }
576 }
577
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000578 SkScalar x = SkScalarMul(col, w);
579 SkScalar y = SkScalarMul(row, h);
580 SkPoint controlPts[] = {
581 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
582 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
583 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
584 };
585 SkPoint chopped[5];
586 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
587
588 SkPaint ctrlPtPaint;
589 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
590 for (int i = 0; i < 3; ++i) {
591 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
592 }
593
594 SkPaint polyPaint;
595 polyPaint.setColor(0xffA0A0A0);
596 polyPaint.setStrokeWidth(0);
597 polyPaint.setStyle(SkPaint::kStroke_Style);
598 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
599
600 SkPaint choppedPtPaint;
601 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
602
603 for (int c = 0; c < cnt; ++c) {
604 SkPoint* pts = chopped + 2 * c;
605
606 for (int i = 0; i < 3; ++i) {
607 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
608 }
609
610 SkRect bounds;
611 bounds.set(pts, 3);
612
613 SkPaint boundsPaint;
614 boundsPaint.setColor(0xff808080);
615 boundsPaint.setStrokeWidth(0);
616 boundsPaint.setStyle(SkPaint::kStroke_Style);
617 canvas->drawRect(bounds, boundsPaint);
618
joshualitt50408ad2014-11-03 12:31:14 -0800619 GrTestTarget tt;
620 context->getTestTarget(&tt);
621 SkASSERT(tt.target());
622
egdaniel8dd688b2015-01-22 10:16:09 -0800623 GrPipelineBuilder pipelineBuilder;
egdaniel8dd688b2015-01-22 10:16:09 -0800624 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000625
joshualitt3f284d72015-02-11 11:34:58 -0800626 GrPathUtils::QuadUVMatrix DevToUV(pts);
627
628 BezierQuadTestBatch::Geometry geometry;
629 geometry.fColor = gp->color();
630 geometry.fBounds = bounds;
631
632 SkAutoTUnref<GrBatch> batch(BezierQuadTestBatch::Create(gp, geometry, DevToUV));
633
634 tt.target()->drawBatch(&pipelineBuilder, batch, NULL);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000635 }
636 ++col;
637 if (numCols == col) {
638 col = 0;
639 ++row;
640 }
641 }
642 }
643 }
644
645private:
646 typedef GM INHERITED;
647};
648
649DEF_GM( return SkNEW(BezierCubicEffects); )
650DEF_GM( return SkNEW(BezierConicEffects); )
651DEF_GM( return SkNEW(BezierQuadEffects); )
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000652
653}
654
655#endif