blob: f8d184958dd5ae6a84d8ec7d5f86672a335941c0 [file] [log] [blame]
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +00001/*
2 * Copyright 2014 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
12#if SK_SUPPORT_GPU
13
14#include "GrContext.h"
joshualitt5478d422014-11-14 16:00:38 -080015#include "GrDefaultGeoProcFactory.h"
robertphillips391395d2016-03-02 09:26:36 -080016#include "GrDrawContextPriv.h"
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000017#include "GrPathUtils.h"
18#include "GrTest.h"
19#include "SkColorPriv.h"
20#include "SkDevice.h"
21#include "SkGeometry.h"
22#include "SkTLList.h"
23
joshualitt2771b562015-08-07 12:46:26 -070024#include "batches/GrTestBatch.h"
bsalomon16b99132015-08-13 14:55:50 -070025#include "batches/GrVertexBatch.h"
joshualitt2771b562015-08-07 12:46:26 -070026
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000027#include "effects/GrConvexPolyEffect.h"
28
bsalomon342bfc22016-04-01 06:06:20 -070029/** outset rendered rect to visualize anti-aliased poly edges */
30static SkRect outset(const SkRect& unsorted) {
31 SkRect r = unsorted;
32 r.outset(5.f, 5.f);
33 return r;
34}
joshualitt95964c62015-02-11 13:45:50 -080035
bsalomon342bfc22016-04-01 06:06:20 -070036/** sorts a rect */
37static SkRect sorted_rect(const SkRect& unsorted) {
38 SkRect r = unsorted;
39 r.sort();
40 return r;
41}
42
43namespace skiagm {
44class PolyBoundsBatch : public GrTestBatch {
joshualitt95964c62015-02-11 13:45:50 -080045public:
reed1b55a962015-09-17 20:16:13 -070046 DEFINE_BATCH_CLASS_ID
joshualitt95964c62015-02-11 13:45:50 -080047
bsalomon342bfc22016-04-01 06:06:20 -070048 const char* name() const override { return "PolyBoundsBatch"; }
joshualitt95964c62015-02-11 13:45:50 -080049
bsalomon342bfc22016-04-01 06:06:20 -070050 PolyBoundsBatch(const SkRect& rect, GrColor color)
51 : INHERITED(ClassID(), outset(sorted_rect(rect)), color)
52 , fRect(outset(rect)) {
joshualitt95964c62015-02-11 13:45:50 -080053 }
54
55private:
bsalomon342bfc22016-04-01 06:06:20 -070056 void onPrepareDraws(Target* target) const override {
57 using namespace GrDefaultGeoProcFactory;
joshualitt95964c62015-02-11 13:45:50 -080058
bsalomon342bfc22016-04-01 06:06:20 -070059 Color color(this->color());
60 Coverage coverage(Coverage::kSolid_Type);
61 LocalCoords localCoords(LocalCoords::kUnused_Type);
62 SkAutoTUnref<const GrGeometryProcessor> gp(
63 GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I()));
joshualitt95964c62015-02-11 13:45:50 -080064
bsalomon342bfc22016-04-01 06:06:20 -070065 size_t vertexStride = gp->getVertexStride();
bsalomonb5238a72015-05-05 07:49:49 -070066 SkASSERT(vertexStride == sizeof(SkPoint));
67 QuadHelper helper;
bsalomon75398562015-08-17 12:55:38 -070068 SkPoint* verts = reinterpret_cast<SkPoint*>(helper.init(target, vertexStride, 1));
bsalomonb5238a72015-05-05 07:49:49 -070069 if (!verts) {
joshualitt4b31de82015-03-05 14:33:41 -080070 return;
71 }
72
bsalomon342bfc22016-04-01 06:06:20 -070073 fRect.toQuad(verts);
joshualitt95964c62015-02-11 13:45:50 -080074
bsalomon342bfc22016-04-01 06:06:20 -070075 helper.recordDraw(target, gp);
joshualitt95964c62015-02-11 13:45:50 -080076 }
77
bsalomon342bfc22016-04-01 06:06:20 -070078 SkRect fRect;
joshualitt95964c62015-02-11 13:45:50 -080079
joshualitt95964c62015-02-11 13:45:50 -080080 typedef GrTestBatch INHERITED;
81};
82
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000083/**
joshualittb0a8a372014-09-23 09:50:21 -070084 * This GM directly exercises a GrProcessor that draws convex polygons.
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000085 */
86class ConvexPolyEffect : public GM {
87public:
88 ConvexPolyEffect() {
89 this->setBGColor(0xFFFFFFFF);
90 }
91
92protected:
mtklein36352bf2015-03-25 18:17:31 -070093 SkString onShortName() override {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000094 return SkString("convex_poly_effect");
95 }
96
mtklein36352bf2015-03-25 18:17:31 -070097 SkISize onISize() override {
tfarinaf5393182014-06-09 23:59:03 -070098 return SkISize::Make(720, 800);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +000099 }
100
mtklein36352bf2015-03-25 18:17:31 -0700101 void onOnceBeforeDraw() override {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000102 SkPath tri;
103 tri.moveTo(5.f, 5.f);
104 tri.lineTo(100.f, 20.f);
105 tri.lineTo(15.f, 100.f);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000106
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000107 fPaths.addToTail(tri);
108 fPaths.addToTail(SkPath())->reverseAddPath(tri);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000109
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000110 tri.close();
111 fPaths.addToTail(tri);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000112
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000113 SkPath ngon;
114 static const SkScalar kRadius = 50.f;
115 const SkPoint center = { kRadius, kRadius };
116 for (int i = 0; i < GrConvexPolyEffect::kMaxEdges; ++i) {
117 SkScalar angle = 2 * SK_ScalarPI * i / GrConvexPolyEffect::kMaxEdges;
118 SkPoint point;
119 point.fY = SkScalarSinCos(angle, &point.fX);
120 point.scale(kRadius);
121 point = center + point;
122 if (0 == i) {
123 ngon.moveTo(point);
124 } else {
125 ngon.lineTo(point);
126 }
127 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000128
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000129 fPaths.addToTail(ngon);
130 SkMatrix scaleM;
131 scaleM.setScale(1.1f, 0.4f);
132 ngon.transform(scaleM);
133 fPaths.addToTail(ngon);
skia.committer@gmail.comf0b0cda2014-02-09 03:02:01 +0000134
bsalomon7888de02016-03-28 15:04:45 -0700135 SkPath linePath;
136 linePath.moveTo(5.f, 5.f);
137 linePath.lineTo(6.f, 6.f);
138 fPaths.addToTail(linePath);
139
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000140 // integer edges
141 fRects.addToTail(SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f));
142 // half-integer edges
143 fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f));
144 // vertically/horizontally thin rects that cover pixel centers
145 fRects.addToTail(SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f));
146 fRects.addToTail(SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 0.75f));
147 // vertically/horizontally thin rects that don't cover pixel centers
148 fRects.addToTail(SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f));
149 fRects.addToTail(SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f));
150 // small in x and y
151 fRects.addToTail(SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f));
152 // inverted in x and y
153 fRects.addToTail(SkRect::MakeLTRB(100.f, 50.5f, 5.f, 0.5f));
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000154 }
155
mtklein36352bf2015-03-25 18:17:31 -0700156 void onDraw(SkCanvas* canvas) override {
reed@google.com9c135db2014-03-12 18:28:35 +0000157 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
halcanary96fcdcc2015-08-27 07:41:13 -0700158 if (nullptr == rt) {
halcanary2a243382015-09-09 08:16:41 -0700159 skiagm::GM::DrawGpuOnlyMessage(canvas);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000160 return;
161 }
162 GrContext* context = rt->getContext();
halcanary96fcdcc2015-08-27 07:41:13 -0700163 if (nullptr == context) {
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000164 return;
165 }
166
joshualittf5883a62016-01-13 07:47:38 -0800167 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt));
168 if (!drawContext) {
169 return;
170 }
171
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000172 SkScalar y = 0;
bsalomon7888de02016-03-28 15:04:45 -0700173 static const SkScalar kDX = 12.f;
bsalomonf045d602015-11-18 19:01:12 -0800174 for (PathList::Iter iter(fPaths, PathList::Iter::kHead_IterStart);
bsalomon49f085d2014-09-05 13:34:00 -0700175 iter.get();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000176 iter.next()) {
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000177 const SkPath* path = iter.get();
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000178 SkScalar x = 0;
179
joshualittb0a8a372014-09-23 09:50:21 -0700180 for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
robertphillips1d24b8d2015-03-26 19:57:08 -0700181 const SkMatrix m = SkMatrix::MakeTrans(x, y);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000182 SkPath p;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000183 path->transform(m, &p);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000184
joshualittb0a8a372014-09-23 09:50:21 -0700185 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
186 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, p));
187 if (!fp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000188 continue;
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000189 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000190
egdaniel8dd688b2015-01-22 10:16:09 -0800191 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800192 pipelineBuilder.setXPFactory(
193 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
bsalomonac856c92015-08-27 06:30:17 -0700194 pipelineBuilder.addCoverageFragmentProcessor(fp);
egdaniel8dd688b2015-01-22 10:16:09 -0800195 pipelineBuilder.setRenderTarget(rt);
joshualitt9853cce2014-11-17 14:22:48 -0800196
bsalomon342bfc22016-04-01 06:06:20 -0700197 SkAutoTUnref<GrDrawBatch> batch(new PolyBoundsBatch(p.getBounds(), 0xff000000));
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000198
robertphillips391395d2016-03-02 09:26:36 -0800199 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000200
bsalomon7888de02016-03-28 15:04:45 -0700201 x += SkScalarCeilToScalar(path->getBounds().width() + kDX);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000202 }
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000203
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000204 // Draw AA and non AA paths using normal API for reference.
205 canvas->save();
206 canvas->translate(x, y);
207 SkPaint paint;
208 canvas->drawPath(*path, paint);
209 canvas->translate(path->getBounds().width() + 10.f, 0);
210 paint.setAntiAlias(true);
211 canvas->drawPath(*path, paint);
212 canvas->restore();
skia.committer@gmail.com4c18e9f2014-01-31 03:01:59 +0000213
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000214 y += SkScalarCeilToScalar(path->getBounds().height() + 20.f);
215 }
216
bsalomonf045d602015-11-18 19:01:12 -0800217 for (RectList::Iter iter(fRects, RectList::Iter::kHead_IterStart);
bsalomon49f085d2014-09-05 13:34:00 -0700218 iter.get();
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000219 iter.next()) {
220
221 SkScalar x = 0;
222
joshualittb0a8a372014-09-23 09:50:21 -0700223 for (int et = 0; et < kGrProcessorEdgeTypeCnt; ++et) {
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000224 SkRect rect = *iter.get();
225 rect.offset(x, y);
joshualittb0a8a372014-09-23 09:50:21 -0700226 GrPrimitiveEdgeType edgeType = (GrPrimitiveEdgeType) et;
227 SkAutoTUnref<GrFragmentProcessor> fp(GrConvexPolyEffect::Create(edgeType, rect));
228 if (!fp) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000229 continue;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000230 }
231
egdaniel8dd688b2015-01-22 10:16:09 -0800232 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800233 pipelineBuilder.setXPFactory(
234 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
bsalomonac856c92015-08-27 06:30:17 -0700235 pipelineBuilder.addCoverageFragmentProcessor(fp);
egdaniel8dd688b2015-01-22 10:16:09 -0800236 pipelineBuilder.setRenderTarget(rt);
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000237
bsalomon342bfc22016-04-01 06:06:20 -0700238 SkAutoTUnref<GrDrawBatch> batch(new PolyBoundsBatch(rect, 0xff000000));
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000239
robertphillips391395d2016-03-02 09:26:36 -0800240 drawContext->drawContextPriv().testingOnly_drawBatch(pipelineBuilder, batch);
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000241
bsalomon7888de02016-03-28 15:04:45 -0700242 x += SkScalarCeilToScalar(rect.width() + kDX);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000243 }
244
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000245 // Draw rect without and with AA using normal API for reference
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000246 canvas->save();
247 canvas->translate(x, y);
248 SkPaint paint;
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000249 canvas->drawRect(*iter.get(), paint);
bsalomon7888de02016-03-28 15:04:45 -0700250 x += SkScalarCeilToScalar(iter.get()->width() + kDX);
commit-bot@chromium.orgf0539802014-02-08 19:31:05 +0000251 paint.setAntiAlias(true);
252 canvas->drawRect(*iter.get(), paint);
253 canvas->restore();
254
commit-bot@chromium.orgd85f32c2014-02-28 14:43:26 +0000255 y += SkScalarCeilToScalar(iter.get()->height() + 20.f);
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000256 }
257 }
258
259private:
bsalomonf045d602015-11-18 19:01:12 -0800260 typedef SkTLList<SkPath, 1> PathList;
261 typedef SkTLList<SkRect, 1> RectList;
262 PathList fPaths;
263 RectList fRects;
skia.committer@gmail.comf0b0cda2014-02-09 03:02:01 +0000264
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000265 typedef GM INHERITED;
266};
267
halcanary385fe4d2015-08-26 13:07:48 -0700268DEF_GM(return new ConvexPolyEffect;)
commit-bot@chromium.orgc3fe5492014-01-30 18:15:51 +0000269}
270
271#endif