blob: 61d3795225ee0b3c9c20f276b8543382e00eb261 [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
bsalomon342bfc22016-04-01 06:06:20 -070037 BezierCubicOrConicTestBatch(const GrGeometryProcessor* gp, const SkRect& bounds,
38 GrColor color, const SkScalar klmEqs[9], SkScalar sign)
39 : INHERITED(ClassID(), bounds, color)
40 , fGeometryProcessor(SkRef(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 }
bsalomon342bfc22016-04-01 06:06:20 -070070 helper.recordDraw(target, fGeometryProcessor);
joshualitt95964c62015-02-11 13:45:50 -080071 }
72
bsalomon342bfc22016-04-01 06:06:20 -070073 SkScalar fKlmEqs[9];
74 SkScalar fSign;
75 SkAutoTUnref<const 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 {
reed@google.com9c135db2014-03-12 18:28:35 +0000102 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -0700103 if (nullptr == rt) {
halcanary2a243382015-09-09 08:16:41 -0700104 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000105 return;
106 }
107 GrContext* context = rt->getContext();
halcanary96fcdcc2015-08-27 07:41:13 -0700108 if (nullptr == context) {
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000109 return;
110 }
111
joshualittf5883a62016-01-13 07:47:38 -0800112 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
113 if (!drawContext) {
114 return;
115 }
116
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000117 struct Vertex {
118 SkPoint fPosition;
119 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
120 };
121
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000122 static const int kNumCubics = 15;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000123 SkRandom rand;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000124
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000125 // Mult by 3 for each edge effect type
126 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumCubics*3)));
127 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumCubics*3) / numCols);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000128 SkScalar w = SkIntToScalar(rt->width()) / numCols;
129 SkScalar h = SkIntToScalar(rt->height()) / numRows;
130 int row = 0;
131 int col = 0;
joshualitt88c23fc2015-05-13 14:18:07 -0700132 static const GrColor color = 0xff000000;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000133
134 for (int i = 0; i < kNumCubics; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000135 SkPoint baseControlPts[] = {
136 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
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)}
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000140 };
joshualittb0a8a372014-09-23 09:50:21 -0700141 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
142 SkAutoTUnref<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800143 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
144 gp.reset(GrCubicEffect::Create(color, SkMatrix::I(), et,
145 *context->caps()));
146 if (!gp) {
147 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000148 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000149 SkScalar x = SkScalarMul(col, w);
150 SkScalar y = SkScalarMul(row, h);
151 SkPoint controlPts[] = {
152 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
153 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
154 {x + baseControlPts[2].fX, y + baseControlPts[2].fY},
155 {x + baseControlPts[3].fX, y + baseControlPts[3].fY}
156 };
157 SkPoint chopped[10];
158 SkScalar klmEqs[9];
159 SkScalar klmSigns[3];
160 int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts,
161 chopped,
162 klmEqs,
163 klmSigns);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000164
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000165 SkPaint ctrlPtPaint;
166 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000167 for (int i = 0; i < 4; ++i) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000168 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000169 }
170
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000171 SkPaint polyPaint;
172 polyPaint.setColor(0xffA0A0A0);
173 polyPaint.setStrokeWidth(0);
174 polyPaint.setStyle(SkPaint::kStroke_Style);
175 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, controlPts, polyPaint);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000176
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000177 SkPaint choppedPtPaint;
178 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000179
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000180 for (int c = 0; c < cnt; ++c) {
181 SkPoint* pts = chopped + 3 * c;
182
183 for (int i = 0; i < 4; ++i) {
184 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
185 }
186
187 SkRect bounds;
188 bounds.set(pts, 4);
189
190 SkPaint boundsPaint;
191 boundsPaint.setColor(0xff808080);
192 boundsPaint.setStrokeWidth(0);
193 boundsPaint.setStyle(SkPaint::kStroke_Style);
194 canvas->drawRect(bounds, boundsPaint);
195
egdaniel8dd688b2015-01-22 10:16:09 -0800196 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800197 pipelineBuilder.setXPFactory(
198 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
egdaniel8dd688b2015-01-22 10:16:09 -0800199 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000200
bsalomonabd30f52015-08-13 13:34:48 -0700201 SkAutoTUnref<GrDrawBatch> batch(
bsalomon342bfc22016-04-01 06:06:20 -0700202 new BezierCubicOrConicTestBatch(gp, bounds, color, klmEqs, klmSigns[c]));
joshualitt95964c62015-02-11 13:45:50 -0800203
robertphillips391395d2016-03-02 09:26:36 -0800204 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000205 }
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000206 ++col;
207 if (numCols == col) {
208 col = 0;
209 ++row;
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000210 }
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000211 }
212 }
213 }
214
215private:
216 typedef GM INHERITED;
217};
218
219//////////////////////////////////////////////////////////////////////////////
220
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000221/**
222 * This GM directly exercises effects that draw Bezier curves in the GPU backend.
223 */
224class BezierConicEffects : public GM {
225public:
226 BezierConicEffects() {
227 this->setBGColor(0xFFFFFFFF);
228 }
229
230protected:
mtklein36352bf2015-03-25 18:17:31 -0700231 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000232 return SkString("bezier_conic_effects");
233 }
234
mtklein36352bf2015-03-25 18:17:31 -0700235 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700236 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000237 }
238
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000239
mtklein36352bf2015-03-25 18:17:31 -0700240 void onDraw(SkCanvas* canvas) override {
reed@google.com9c135db2014-03-12 18:28:35 +0000241 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -0700242 if (nullptr == rt) {
halcanary2a243382015-09-09 08:16:41 -0700243 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000244 return;
245 }
246 GrContext* context = rt->getContext();
halcanary96fcdcc2015-08-27 07:41:13 -0700247 if (nullptr == context) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000248 return;
249 }
250
joshualittf5883a62016-01-13 07:47:38 -0800251 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
252 if (!drawContext) {
253 return;
254 }
255
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000256 struct Vertex {
257 SkPoint fPosition;
258 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
259 };
260
261 static const int kNumConics = 10;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000262 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000263
264 // Mult by 3 for each edge effect type
265 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumConics*3)));
266 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumConics*3) / numCols);
267 SkScalar w = SkIntToScalar(rt->width()) / numCols;
268 SkScalar h = SkIntToScalar(rt->height()) / numRows;
269 int row = 0;
270 int col = 0;
joshualitt88c23fc2015-05-13 14:18:07 -0700271 static const GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000272
273 for (int i = 0; i < kNumConics; ++i) {
274 SkPoint baseControlPts[] = {
275 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
276 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
277 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
278 };
279 SkScalar weight = rand.nextRangeF(0.f, 2.f);
joshualittb0a8a372014-09-23 09:50:21 -0700280 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
281 SkAutoTUnref<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800282 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
283 gp.reset(GrConicEffect::Create(color, SkMatrix::I(), et,
284 *context->caps(), SkMatrix::I(), false));
285 if (!gp) {
286 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000287 }
288
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000289 SkScalar x = SkScalarMul(col, w);
290 SkScalar y = SkScalarMul(row, h);
291 SkPoint controlPts[] = {
292 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
293 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
294 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
295 };
296 SkConic dst[4];
297 SkScalar klmEqs[9];
298 int cnt = chop_conic(controlPts, dst, weight);
299 GrPathUtils::getConicKLM(controlPts, weight, klmEqs);
300
301 SkPaint ctrlPtPaint;
302 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
303 for (int i = 0; i < 3; ++i) {
304 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
305 }
306
307 SkPaint polyPaint;
308 polyPaint.setColor(0xffA0A0A0);
309 polyPaint.setStrokeWidth(0);
310 polyPaint.setStyle(SkPaint::kStroke_Style);
311 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
312
313 SkPaint choppedPtPaint;
314 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
315
316 for (int c = 0; c < cnt; ++c) {
317 SkPoint* pts = dst[c].fPts;
318 for (int i = 0; i < 3; ++i) {
319 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
320 }
321
322 SkRect bounds;
323 //SkPoint bPts[] = {{0.f, 0.f}, {800.f, 800.f}};
324 //bounds.set(bPts, 2);
325 bounds.set(pts, 3);
326
327 SkPaint boundsPaint;
328 boundsPaint.setColor(0xff808080);
329 boundsPaint.setStrokeWidth(0);
330 boundsPaint.setStyle(SkPaint::kStroke_Style);
331 canvas->drawRect(bounds, boundsPaint);
332
egdaniel8dd688b2015-01-22 10:16:09 -0800333 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800334 pipelineBuilder.setXPFactory(
335 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
egdaniel8dd688b2015-01-22 10:16:09 -0800336 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000337
bsalomonabd30f52015-08-13 13:34:48 -0700338 SkAutoTUnref<GrDrawBatch> batch(
bsalomon342bfc22016-04-01 06:06:20 -0700339 new BezierCubicOrConicTestBatch(gp, bounds, color, klmEqs, 1.f));
joshualitt95964c62015-02-11 13:45:50 -0800340
robertphillips391395d2016-03-02 09:26:36 -0800341 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000342 }
343 ++col;
344 if (numCols == col) {
345 col = 0;
346 ++row;
347 }
348 }
349 }
350 }
351
352private:
353 // Uses the max curvature function for quads to estimate
354 // where to chop the conic. If the max curvature is not
355 // found along the curve segment it will return 1 and
356 // dst[0] is the original conic. If it returns 2 the dst[0]
357 // and dst[1] are the two new conics.
358 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
359 SkScalar t = SkFindQuadMaxCurvature(src);
360 if (t == 0) {
361 if (dst) {
362 dst[0].set(src, weight);
363 }
364 return 1;
365 } else {
366 if (dst) {
367 SkConic conic;
368 conic.set(src, weight);
369 conic.chopAt(t, dst);
370 }
371 return 2;
372 }
373 }
374
375 // Calls split_conic on the entire conic and then once more on each subsection.
376 // Most cases will result in either 1 conic (chop point is not within t range)
377 // or 3 points (split once and then one subsection is split again).
378 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
379 SkConic dstTemp[2];
380 int conicCnt = split_conic(src, dstTemp, weight);
381 if (2 == conicCnt) {
382 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
383 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dstTemp[1].fW);
384 } else {
385 dst[0] = dstTemp[0];
386 }
387 return conicCnt;
388 }
389
390 typedef GM INHERITED;
391};
392
393//////////////////////////////////////////////////////////////////////////////
joshualitt95964c62015-02-11 13:45:50 -0800394
395class BezierQuadTestBatch : public GrTestBatch {
396public:
reed1b55a962015-09-17 20:16:13 -0700397 DEFINE_BATCH_CLASS_ID
mtklein36352bf2015-03-25 18:17:31 -0700398 const char* name() const override { return "BezierQuadTestBatch"; }
joshualitt95964c62015-02-11 13:45:50 -0800399
bsalomon342bfc22016-04-01 06:06:20 -0700400 BezierQuadTestBatch(const GrGeometryProcessor* gp, const SkRect& bounds, GrColor color,
401 const GrPathUtils::QuadUVMatrix& devToUV)
402 : INHERITED(ClassID(), bounds, color)
403 , fDevToUV(devToUV)
404 , fGeometryProcessor(SkRef(gp)) {
joshualitt95964c62015-02-11 13:45:50 -0800405 }
406
407private:
joshualitt95964c62015-02-11 13:45:50 -0800408
409 struct Vertex {
410 SkPoint fPosition;
411 float fKLM[4]; // The last value is ignored. The effect expects a vec4f.
412 };
413
bsalomon342bfc22016-04-01 06:06:20 -0700414 void onPrepareDraws(Target* target) const override {
bsalomonb5238a72015-05-05 07:49:49 -0700415 QuadHelper helper;
bsalomon342bfc22016-04-01 06:06:20 -0700416 size_t vertexStride = fGeometryProcessor->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -0700417 SkASSERT(vertexStride == sizeof(Vertex));
bsalomon75398562015-08-17 12:55:38 -0700418 Vertex* verts = reinterpret_cast<Vertex*>(helper.init(target, vertexStride, 1));
bsalomonb5238a72015-05-05 07:49:49 -0700419 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -0800420 return;
421 }
bsalomon342bfc22016-04-01 06:06:20 -0700422 const SkRect& bounds = this->bounds();
423 verts[0].fPosition.setRectFan(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom,
joshualitt95964c62015-02-11 13:45:50 -0800424 sizeof(Vertex));
joshualitt95964c62015-02-11 13:45:50 -0800425 fDevToUV.apply<4, sizeof(Vertex), sizeof(SkPoint)>(verts);
bsalomon342bfc22016-04-01 06:06:20 -0700426 helper.recordDraw(target, fGeometryProcessor);
joshualitt95964c62015-02-11 13:45:50 -0800427 }
428
bsalomon342bfc22016-04-01 06:06:20 -0700429 GrPathUtils::QuadUVMatrix fDevToUV;
430 SkAutoTUnref<const GrGeometryProcessor> fGeometryProcessor;
joshualitt95964c62015-02-11 13:45:50 -0800431
432 static const int kVertsPerCubic = 4;
433 static const int kIndicesPerCubic = 6;
434
435 typedef GrTestBatch INHERITED;
436};
437
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000438/**
439 * This GM directly exercises effects that draw Bezier quad curves in the GPU backend.
440 */
441class BezierQuadEffects : public GM {
442public:
443 BezierQuadEffects() {
444 this->setBGColor(0xFFFFFFFF);
445 }
446
447protected:
mtklein36352bf2015-03-25 18:17:31 -0700448 SkString onShortName() override {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000449 return SkString("bezier_quad_effects");
450 }
451
mtklein36352bf2015-03-25 18:17:31 -0700452 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -0700453 return SkISize::Make(800, 800);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000454 }
455
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000456
mtklein36352bf2015-03-25 18:17:31 -0700457 void onDraw(SkCanvas* canvas) override {
reed@google.com9c135db2014-03-12 18:28:35 +0000458 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -0700459 if (nullptr == rt) {
halcanary2a243382015-09-09 08:16:41 -0700460 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000461 return;
462 }
463 GrContext* context = rt->getContext();
halcanary96fcdcc2015-08-27 07:41:13 -0700464 if (nullptr == context) {
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000465 return;
466 }
467
joshualittf5883a62016-01-13 07:47:38 -0800468 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
469 if (!drawContext) {
470 return;
471 }
472
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000473 struct Vertex {
474 SkPoint fPosition;
475 float fUV[4]; // The last two values are ignored. The effect expects a vec4f.
476 };
477
478 static const int kNumQuads = 5;
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000479 SkRandom rand;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000480
481 int numCols = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(kNumQuads*3)));
482 int numRows = SkScalarCeilToInt(SkIntToScalar(kNumQuads*3) / numCols);
483 SkScalar w = SkIntToScalar(rt->width()) / numCols;
484 SkScalar h = SkIntToScalar(rt->height()) / numRows;
485 int row = 0;
486 int col = 0;
joshualitt88c23fc2015-05-13 14:18:07 -0700487 static const GrColor color = 0xff000000;
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000488
489 for (int i = 0; i < kNumQuads; ++i) {
490 SkPoint baseControlPts[] = {
491 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
492 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)},
493 {rand.nextRangeF(0.f, w), rand.nextRangeF(0.f, h)}
494 };
joshualittb0a8a372014-09-23 09:50:21 -0700495 for(int edgeType = 0; edgeType < kGrProcessorEdgeTypeCnt; ++edgeType) {
496 SkAutoTUnref<GrGeometryProcessor> gp;
joshualittf5883a62016-01-13 07:47:38 -0800497 GrPrimitiveEdgeType et = (GrPrimitiveEdgeType)edgeType;
498 gp.reset(GrQuadEffect::Create(color, SkMatrix::I(), et,
499 *context->caps(), SkMatrix::I(), false));
500 if (!gp) {
501 continue;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000502 }
503
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000504 SkScalar x = SkScalarMul(col, w);
505 SkScalar y = SkScalarMul(row, h);
506 SkPoint controlPts[] = {
507 {x + baseControlPts[0].fX, y + baseControlPts[0].fY},
508 {x + baseControlPts[1].fX, y + baseControlPts[1].fY},
509 {x + baseControlPts[2].fX, y + baseControlPts[2].fY}
510 };
511 SkPoint chopped[5];
512 int cnt = SkChopQuadAtMaxCurvature(controlPts, chopped);
513
514 SkPaint ctrlPtPaint;
515 ctrlPtPaint.setColor(rand.nextU() | 0xFF000000);
516 for (int i = 0; i < 3; ++i) {
517 canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint);
518 }
519
520 SkPaint polyPaint;
521 polyPaint.setColor(0xffA0A0A0);
522 polyPaint.setStrokeWidth(0);
523 polyPaint.setStyle(SkPaint::kStroke_Style);
524 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, controlPts, polyPaint);
525
526 SkPaint choppedPtPaint;
527 choppedPtPaint.setColor(~ctrlPtPaint.getColor() | 0xFF000000);
528
529 for (int c = 0; c < cnt; ++c) {
530 SkPoint* pts = chopped + 2 * c;
531
532 for (int i = 0; i < 3; ++i) {
533 canvas->drawCircle(pts[i].fX, pts[i].fY, 3.f, choppedPtPaint);
534 }
535
536 SkRect bounds;
537 bounds.set(pts, 3);
538
539 SkPaint boundsPaint;
540 boundsPaint.setColor(0xff808080);
541 boundsPaint.setStrokeWidth(0);
542 boundsPaint.setStyle(SkPaint::kStroke_Style);
543 canvas->drawRect(bounds, boundsPaint);
544
egdaniel8dd688b2015-01-22 10:16:09 -0800545 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800546 pipelineBuilder.setXPFactory(
547 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
joshualitt94dff152015-02-11 13:03:15 -0800548 pipelineBuilder.setRenderTarget(rt);
joshualitt3f284d72015-02-11 11:34:58 -0800549
joshualitt95964c62015-02-11 13:45:50 -0800550 GrPathUtils::QuadUVMatrix DevToUV(pts);
551
bsalomon342bfc22016-04-01 06:06:20 -0700552 SkAutoTUnref<GrDrawBatch> batch(
553 new BezierQuadTestBatch(gp, bounds, color, DevToUV));
joshualitt95964c62015-02-11 13:45:50 -0800554
robertphillips391395d2016-03-02 09:26:36 -0800555 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
commit-bot@chromium.org53a0b6c2013-08-23 18:05:01 +0000556 }
557 ++col;
558 if (numCols == col) {
559 col = 0;
560 ++row;
561 }
562 }
563 }
564 }
565
566private:
567 typedef GM INHERITED;
568};
569
halcanary385fe4d2015-08-26 13:07:48 -0700570DEF_GM(return new BezierCubicEffects;)
571DEF_GM(return new BezierConicEffects;)
572DEF_GM(return new BezierQuadEffects;)
commit-bot@chromium.org78a10782013-08-21 19:27:48 +0000573}
574
575#endif